diff --git a/owncloudorgnew/404.php b/404.php similarity index 100% rename from owncloudorgnew/404.php rename to 404.php diff --git a/owncloudorgnew/CHANGELOG.md b/CHANGELOG.md similarity index 100% rename from owncloudorgnew/CHANGELOG.md rename to CHANGELOG.md diff --git a/owncloudorgnew/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 100% rename from owncloudorgnew/CONTRIBUTING.md rename to CONTRIBUTING.md diff --git a/owncloudorgnew/Gruntfile.js b/Gruntfile.js similarity index 100% rename from owncloudorgnew/Gruntfile.js rename to Gruntfile.js diff --git a/owncloudorgnew/LICENSE.md b/LICENSE.md similarity index 100% rename from owncloudorgnew/LICENSE.md rename to LICENSE.md diff --git a/owncloudorgnew/README.md b/README.md similarity index 100% rename from owncloudorgnew/README.md rename to README.md diff --git a/owncloudorgnew/apps.php b/apps.php similarity index 100% rename from owncloudorgnew/apps.php rename to apps.php diff --git a/owncloudorgnew/assets/css/editor-style.css b/assets/css/editor-style.css similarity index 100% rename from owncloudorgnew/assets/css/editor-style.css rename to assets/css/editor-style.css diff --git a/owncloudorgnew/assets/css/main.min.css b/assets/css/main.min.css similarity index 100% rename from owncloudorgnew/assets/css/main.min.css rename to assets/css/main.min.css diff --git a/owncloudorgnew/assets/fonts/FontAwesome.otf b/assets/fonts/FontAwesome.otf similarity index 100% rename from owncloudorgnew/assets/fonts/FontAwesome.otf rename to assets/fonts/FontAwesome.otf diff --git a/owncloudorgnew/assets/fonts/fontawesome-webfont.eot b/assets/fonts/fontawesome-webfont.eot similarity index 100% rename from owncloudorgnew/assets/fonts/fontawesome-webfont.eot rename to assets/fonts/fontawesome-webfont.eot diff --git a/owncloudorgnew/assets/fonts/fontawesome-webfont.svg b/assets/fonts/fontawesome-webfont.svg similarity index 100% rename from owncloudorgnew/assets/fonts/fontawesome-webfont.svg rename to assets/fonts/fontawesome-webfont.svg diff --git a/owncloudorgnew/assets/fonts/fontawesome-webfont.ttf b/assets/fonts/fontawesome-webfont.ttf similarity index 100% rename from owncloudorgnew/assets/fonts/fontawesome-webfont.ttf rename to assets/fonts/fontawesome-webfont.ttf diff --git a/owncloudorgnew/assets/fonts/fontawesome-webfont.woff b/assets/fonts/fontawesome-webfont.woff similarity index 100% rename from owncloudorgnew/assets/fonts/fontawesome-webfont.woff rename to assets/fonts/fontawesome-webfont.woff diff --git a/owncloudorgnew/assets/fonts/glyphicons-halflings-regular.eot b/assets/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from owncloudorgnew/assets/fonts/glyphicons-halflings-regular.eot rename to assets/fonts/glyphicons-halflings-regular.eot diff --git a/owncloudorgnew/assets/fonts/glyphicons-halflings-regular.svg b/assets/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from owncloudorgnew/assets/fonts/glyphicons-halflings-regular.svg rename to assets/fonts/glyphicons-halflings-regular.svg diff --git a/owncloudorgnew/assets/fonts/glyphicons-halflings-regular.ttf b/assets/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from owncloudorgnew/assets/fonts/glyphicons-halflings-regular.ttf rename to assets/fonts/glyphicons-halflings-regular.ttf diff --git a/owncloudorgnew/assets/fonts/glyphicons-halflings-regular.woff b/assets/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from owncloudorgnew/assets/fonts/glyphicons-halflings-regular.woff rename to assets/fonts/glyphicons-halflings-regular.woff diff --git a/owncloudorgnew/assets/img/.gitignore b/assets/img/.gitignore similarity index 100% rename from owncloudorgnew/assets/img/.gitignore rename to assets/img/.gitignore diff --git a/owncloudorgnew/assets/img/logo_owncloud.png b/assets/img/logo_owncloud.png similarity index 100% rename from owncloudorgnew/assets/img/logo_owncloud.png rename to assets/img/logo_owncloud.png diff --git a/owncloudorgnew/assets/img/ocscreen.png b/assets/img/ocscreen.png similarity index 100% rename from owncloudorgnew/assets/img/ocscreen.png rename to assets/img/ocscreen.png diff --git a/owncloudorgnew/assets/img/ocsync.png b/assets/img/ocsync.png similarity index 100% rename from owncloudorgnew/assets/img/ocsync.png rename to assets/img/ocsync.png diff --git a/owncloudorgnew/assets/js/_main.js b/assets/js/_main.js similarity index 100% rename from owncloudorgnew/assets/js/_main.js rename to assets/js/_main.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/affix.js b/assets/js/plugins/bootstrap/affix.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/affix.js rename to assets/js/plugins/bootstrap/affix.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/alert.js b/assets/js/plugins/bootstrap/alert.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/alert.js rename to assets/js/plugins/bootstrap/alert.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/button.js b/assets/js/plugins/bootstrap/button.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/button.js rename to assets/js/plugins/bootstrap/button.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/carousel.js b/assets/js/plugins/bootstrap/carousel.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/carousel.js rename to assets/js/plugins/bootstrap/carousel.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/collapse.js b/assets/js/plugins/bootstrap/collapse.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/collapse.js rename to assets/js/plugins/bootstrap/collapse.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/dropdown.js b/assets/js/plugins/bootstrap/dropdown.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/dropdown.js rename to assets/js/plugins/bootstrap/dropdown.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/modal.js b/assets/js/plugins/bootstrap/modal.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/modal.js rename to assets/js/plugins/bootstrap/modal.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/popover.js b/assets/js/plugins/bootstrap/popover.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/popover.js rename to assets/js/plugins/bootstrap/popover.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/scrollspy.js b/assets/js/plugins/bootstrap/scrollspy.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/scrollspy.js rename to assets/js/plugins/bootstrap/scrollspy.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/tab.js b/assets/js/plugins/bootstrap/tab.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/tab.js rename to assets/js/plugins/bootstrap/tab.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/tooltip.js b/assets/js/plugins/bootstrap/tooltip.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/tooltip.js rename to assets/js/plugins/bootstrap/tooltip.js diff --git a/owncloudorgnew/assets/js/plugins/bootstrap/transition.js b/assets/js/plugins/bootstrap/transition.js similarity index 100% rename from owncloudorgnew/assets/js/plugins/bootstrap/transition.js rename to assets/js/plugins/bootstrap/transition.js diff --git a/owncloudorgnew/assets/js/scripts.min.js b/assets/js/scripts.min.js similarity index 100% rename from owncloudorgnew/assets/js/scripts.min.js rename to assets/js/scripts.min.js diff --git a/owncloudorgnew/assets/js/vendor/jquery-1.10.2.min.js b/assets/js/vendor/jquery-1.10.2.min.js similarity index 100% rename from owncloudorgnew/assets/js/vendor/jquery-1.10.2.min.js rename to assets/js/vendor/jquery-1.10.2.min.js diff --git a/owncloudorgnew/assets/js/vendor/modernizr-2.7.0.min.js b/assets/js/vendor/modernizr-2.7.0.min.js similarity index 100% rename from owncloudorgnew/assets/js/vendor/modernizr-2.7.0.min.js rename to assets/js/vendor/modernizr-2.7.0.min.js diff --git a/owncloudorgnew/assets/less/app.less b/assets/less/app.less similarity index 100% rename from owncloudorgnew/assets/less/app.less rename to assets/less/app.less diff --git a/owncloudorgnew/assets/less/bootstrap/alerts.less b/assets/less/bootstrap/alerts.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/alerts.less rename to assets/less/bootstrap/alerts.less diff --git a/owncloudorgnew/assets/less/bootstrap/badges.less b/assets/less/bootstrap/badges.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/badges.less rename to assets/less/bootstrap/badges.less diff --git a/owncloudorgnew/assets/less/bootstrap/bootstrap.less b/assets/less/bootstrap/bootstrap.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/bootstrap.less rename to assets/less/bootstrap/bootstrap.less diff --git a/owncloudorgnew/assets/less/bootstrap/breadcrumbs.less b/assets/less/bootstrap/breadcrumbs.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/breadcrumbs.less rename to assets/less/bootstrap/breadcrumbs.less diff --git a/owncloudorgnew/assets/less/bootstrap/button-groups.less b/assets/less/bootstrap/button-groups.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/button-groups.less rename to assets/less/bootstrap/button-groups.less diff --git a/owncloudorgnew/assets/less/bootstrap/buttons.less b/assets/less/bootstrap/buttons.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/buttons.less rename to assets/less/bootstrap/buttons.less diff --git a/owncloudorgnew/assets/less/bootstrap/carousel.less b/assets/less/bootstrap/carousel.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/carousel.less rename to assets/less/bootstrap/carousel.less diff --git a/owncloudorgnew/assets/less/bootstrap/close.less b/assets/less/bootstrap/close.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/close.less rename to assets/less/bootstrap/close.less diff --git a/owncloudorgnew/assets/less/bootstrap/code.less b/assets/less/bootstrap/code.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/code.less rename to assets/less/bootstrap/code.less diff --git a/owncloudorgnew/assets/less/bootstrap/component-animations.less b/assets/less/bootstrap/component-animations.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/component-animations.less rename to assets/less/bootstrap/component-animations.less diff --git a/owncloudorgnew/assets/less/bootstrap/dropdowns.less b/assets/less/bootstrap/dropdowns.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/dropdowns.less rename to assets/less/bootstrap/dropdowns.less diff --git a/owncloudorgnew/assets/less/bootstrap/forms.less b/assets/less/bootstrap/forms.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/forms.less rename to assets/less/bootstrap/forms.less diff --git a/owncloudorgnew/assets/less/bootstrap/glyphicons.less b/assets/less/bootstrap/glyphicons.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/glyphicons.less rename to assets/less/bootstrap/glyphicons.less diff --git a/owncloudorgnew/assets/less/bootstrap/grid.less b/assets/less/bootstrap/grid.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/grid.less rename to assets/less/bootstrap/grid.less diff --git a/owncloudorgnew/assets/less/bootstrap/input-groups.less b/assets/less/bootstrap/input-groups.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/input-groups.less rename to assets/less/bootstrap/input-groups.less diff --git a/owncloudorgnew/assets/less/bootstrap/jumbotron.less b/assets/less/bootstrap/jumbotron.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/jumbotron.less rename to assets/less/bootstrap/jumbotron.less diff --git a/owncloudorgnew/assets/less/bootstrap/labels.less b/assets/less/bootstrap/labels.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/labels.less rename to assets/less/bootstrap/labels.less diff --git a/owncloudorgnew/assets/less/bootstrap/list-group.less b/assets/less/bootstrap/list-group.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/list-group.less rename to assets/less/bootstrap/list-group.less diff --git a/owncloudorgnew/assets/less/bootstrap/media.less b/assets/less/bootstrap/media.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/media.less rename to assets/less/bootstrap/media.less diff --git a/owncloudorgnew/assets/less/bootstrap/mixins.less b/assets/less/bootstrap/mixins.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/mixins.less rename to assets/less/bootstrap/mixins.less diff --git a/owncloudorgnew/assets/less/bootstrap/modals.less b/assets/less/bootstrap/modals.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/modals.less rename to assets/less/bootstrap/modals.less diff --git a/owncloudorgnew/assets/less/bootstrap/navbar.less b/assets/less/bootstrap/navbar.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/navbar.less rename to assets/less/bootstrap/navbar.less diff --git a/owncloudorgnew/assets/less/bootstrap/navs.less b/assets/less/bootstrap/navs.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/navs.less rename to assets/less/bootstrap/navs.less diff --git a/owncloudorgnew/assets/less/bootstrap/normalize.less b/assets/less/bootstrap/normalize.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/normalize.less rename to assets/less/bootstrap/normalize.less diff --git a/owncloudorgnew/assets/less/bootstrap/pager.less b/assets/less/bootstrap/pager.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/pager.less rename to assets/less/bootstrap/pager.less diff --git a/owncloudorgnew/assets/less/bootstrap/pagination.less b/assets/less/bootstrap/pagination.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/pagination.less rename to assets/less/bootstrap/pagination.less diff --git a/owncloudorgnew/assets/less/bootstrap/panels.less b/assets/less/bootstrap/panels.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/panels.less rename to assets/less/bootstrap/panels.less diff --git a/owncloudorgnew/assets/less/bootstrap/popovers.less b/assets/less/bootstrap/popovers.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/popovers.less rename to assets/less/bootstrap/popovers.less diff --git a/owncloudorgnew/assets/less/bootstrap/print.less b/assets/less/bootstrap/print.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/print.less rename to assets/less/bootstrap/print.less diff --git a/owncloudorgnew/assets/less/bootstrap/progress-bars.less b/assets/less/bootstrap/progress-bars.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/progress-bars.less rename to assets/less/bootstrap/progress-bars.less diff --git a/owncloudorgnew/assets/less/bootstrap/responsive-utilities.less b/assets/less/bootstrap/responsive-utilities.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/responsive-utilities.less rename to assets/less/bootstrap/responsive-utilities.less diff --git a/owncloudorgnew/assets/less/bootstrap/scaffolding.less b/assets/less/bootstrap/scaffolding.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/scaffolding.less rename to assets/less/bootstrap/scaffolding.less diff --git a/owncloudorgnew/assets/less/bootstrap/tables.less b/assets/less/bootstrap/tables.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/tables.less rename to assets/less/bootstrap/tables.less diff --git a/owncloudorgnew/assets/less/bootstrap/theme.less b/assets/less/bootstrap/theme.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/theme.less rename to assets/less/bootstrap/theme.less diff --git a/owncloudorgnew/assets/less/bootstrap/thumbnails.less b/assets/less/bootstrap/thumbnails.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/thumbnails.less rename to assets/less/bootstrap/thumbnails.less diff --git a/owncloudorgnew/assets/less/bootstrap/tooltip.less b/assets/less/bootstrap/tooltip.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/tooltip.less rename to assets/less/bootstrap/tooltip.less diff --git a/owncloudorgnew/assets/less/bootstrap/type.less b/assets/less/bootstrap/type.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/type.less rename to assets/less/bootstrap/type.less diff --git a/owncloudorgnew/assets/less/bootstrap/utilities.less b/assets/less/bootstrap/utilities.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/utilities.less rename to assets/less/bootstrap/utilities.less diff --git a/owncloudorgnew/assets/less/bootstrap/variables.less b/assets/less/bootstrap/variables.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/variables.less rename to assets/less/bootstrap/variables.less diff --git a/owncloudorgnew/assets/less/bootstrap/wells.less b/assets/less/bootstrap/wells.less similarity index 100% rename from owncloudorgnew/assets/less/bootstrap/wells.less rename to assets/less/bootstrap/wells.less diff --git a/owncloudorgnew/assets/less/fontawesome/bordered-pulled.less b/assets/less/fontawesome/bordered-pulled.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/bordered-pulled.less rename to assets/less/fontawesome/bordered-pulled.less diff --git a/owncloudorgnew/assets/less/fontawesome/core.less b/assets/less/fontawesome/core.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/core.less rename to assets/less/fontawesome/core.less diff --git a/owncloudorgnew/assets/less/fontawesome/fixed-width.less b/assets/less/fontawesome/fixed-width.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/fixed-width.less rename to assets/less/fontawesome/fixed-width.less diff --git a/owncloudorgnew/assets/less/fontawesome/font-awesome.less b/assets/less/fontawesome/font-awesome.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/font-awesome.less rename to assets/less/fontawesome/font-awesome.less diff --git a/owncloudorgnew/assets/less/fontawesome/icons.less b/assets/less/fontawesome/icons.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/icons.less rename to assets/less/fontawesome/icons.less diff --git a/owncloudorgnew/assets/less/fontawesome/larger.less b/assets/less/fontawesome/larger.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/larger.less rename to assets/less/fontawesome/larger.less diff --git a/owncloudorgnew/assets/less/fontawesome/list.less b/assets/less/fontawesome/list.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/list.less rename to assets/less/fontawesome/list.less diff --git a/owncloudorgnew/assets/less/fontawesome/mixins.less b/assets/less/fontawesome/mixins.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/mixins.less rename to assets/less/fontawesome/mixins.less diff --git a/owncloudorgnew/assets/less/fontawesome/path.less b/assets/less/fontawesome/path.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/path.less rename to assets/less/fontawesome/path.less diff --git a/owncloudorgnew/assets/less/fontawesome/rotated-flipped.less b/assets/less/fontawesome/rotated-flipped.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/rotated-flipped.less rename to assets/less/fontawesome/rotated-flipped.less diff --git a/owncloudorgnew/assets/less/fontawesome/spinning.less b/assets/less/fontawesome/spinning.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/spinning.less rename to assets/less/fontawesome/spinning.less diff --git a/owncloudorgnew/assets/less/fontawesome/stacked.less b/assets/less/fontawesome/stacked.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/stacked.less rename to assets/less/fontawesome/stacked.less diff --git a/owncloudorgnew/assets/less/fontawesome/variables.less b/assets/less/fontawesome/variables.less similarity index 100% rename from owncloudorgnew/assets/less/fontawesome/variables.less rename to assets/less/fontawesome/variables.less diff --git a/owncloudorgnew/base.php b/base.php similarity index 100% rename from owncloudorgnew/base.php rename to base.php diff --git a/owncloudorgnew/blogpage.php b/blogpage.php similarity index 100% rename from owncloudorgnew/blogpage.php rename to blogpage.php diff --git a/owncloudorgnew/blogrss.php b/blogrss.php similarity index 100% rename from owncloudorgnew/blogrss.php rename to blogrss.php diff --git a/owncloudorgnew/contact.php b/contact.php similarity index 100% rename from owncloudorgnew/contact.php rename to contact.php diff --git a/owncloudorgnew/dev.php b/dev.php similarity index 100% rename from owncloudorgnew/dev.php rename to dev.php diff --git a/owncloudorgnew/front-page.php b/front-page.php similarity index 100% rename from owncloudorgnew/front-page.php rename to front-page.php diff --git a/owncloudorgnew/functions.php b/functions.php similarity index 100% rename from owncloudorgnew/functions.php rename to functions.php diff --git a/owncloudorgnew/home.php b/home.php similarity index 100% rename from owncloudorgnew/home.php rename to home.php diff --git a/owncloudorgnew/index.php b/index.php similarity index 100% rename from owncloudorgnew/index.php rename to index.php diff --git a/owncloudorgnew/lang/ar.mo b/lang/ar.mo similarity index 100% rename from owncloudorgnew/lang/ar.mo rename to lang/ar.mo diff --git a/owncloudorgnew/lang/ar.po b/lang/ar.po similarity index 100% rename from owncloudorgnew/lang/ar.po rename to lang/ar.po diff --git a/owncloudorgnew/lang/bg_BG.mo b/lang/bg_BG.mo similarity index 100% rename from owncloudorgnew/lang/bg_BG.mo rename to lang/bg_BG.mo diff --git a/owncloudorgnew/lang/bg_BG.po b/lang/bg_BG.po similarity index 100% rename from owncloudorgnew/lang/bg_BG.po rename to lang/bg_BG.po diff --git a/owncloudorgnew/lang/ca.mo b/lang/ca.mo similarity index 100% rename from owncloudorgnew/lang/ca.mo rename to lang/ca.mo diff --git a/owncloudorgnew/lang/ca.po b/lang/ca.po similarity index 100% rename from owncloudorgnew/lang/ca.po rename to lang/ca.po diff --git a/owncloudorgnew/lang/da_DK.mo b/lang/da_DK.mo similarity index 100% rename from owncloudorgnew/lang/da_DK.mo rename to lang/da_DK.mo diff --git a/owncloudorgnew/lang/da_DK.po b/lang/da_DK.po similarity index 100% rename from owncloudorgnew/lang/da_DK.po rename to lang/da_DK.po diff --git a/owncloudorgnew/lang/de_DE.mo b/lang/de_DE.mo similarity index 100% rename from owncloudorgnew/lang/de_DE.mo rename to lang/de_DE.mo diff --git a/owncloudorgnew/lang/de_DE.po b/lang/de_DE.po similarity index 100% rename from owncloudorgnew/lang/de_DE.po rename to lang/de_DE.po diff --git a/owncloudorgnew/lang/el.mo b/lang/el.mo similarity index 100% rename from owncloudorgnew/lang/el.mo rename to lang/el.mo diff --git a/owncloudorgnew/lang/el.po b/lang/el.po similarity index 100% rename from owncloudorgnew/lang/el.po rename to lang/el.po diff --git a/owncloudorgnew/lang/es_ES.mo b/lang/es_ES.mo similarity index 100% rename from owncloudorgnew/lang/es_ES.mo rename to lang/es_ES.mo diff --git a/owncloudorgnew/lang/es_ES.po b/lang/es_ES.po similarity index 100% rename from owncloudorgnew/lang/es_ES.po rename to lang/es_ES.po diff --git a/owncloudorgnew/lang/fa_IR.mo b/lang/fa_IR.mo similarity index 100% rename from owncloudorgnew/lang/fa_IR.mo rename to lang/fa_IR.mo diff --git a/owncloudorgnew/lang/fa_IR.po b/lang/fa_IR.po similarity index 100% rename from owncloudorgnew/lang/fa_IR.po rename to lang/fa_IR.po diff --git a/owncloudorgnew/lang/fi_FI.mo b/lang/fi_FI.mo similarity index 100% rename from owncloudorgnew/lang/fi_FI.mo rename to lang/fi_FI.mo diff --git a/owncloudorgnew/lang/fi_FI.po b/lang/fi_FI.po similarity index 100% rename from owncloudorgnew/lang/fi_FI.po rename to lang/fi_FI.po diff --git a/owncloudorgnew/lang/fr_FR.mo b/lang/fr_FR.mo similarity index 100% rename from owncloudorgnew/lang/fr_FR.mo rename to lang/fr_FR.mo diff --git a/owncloudorgnew/lang/fr_FR.po b/lang/fr_FR.po similarity index 100% rename from owncloudorgnew/lang/fr_FR.po rename to lang/fr_FR.po diff --git a/owncloudorgnew/lang/hu_HU.mo b/lang/hu_HU.mo similarity index 100% rename from owncloudorgnew/lang/hu_HU.mo rename to lang/hu_HU.mo diff --git a/owncloudorgnew/lang/hu_HU.po b/lang/hu_HU.po similarity index 100% rename from owncloudorgnew/lang/hu_HU.po rename to lang/hu_HU.po diff --git a/owncloudorgnew/lang/id_ID.mo b/lang/id_ID.mo similarity index 100% rename from owncloudorgnew/lang/id_ID.mo rename to lang/id_ID.mo diff --git a/owncloudorgnew/lang/id_ID.po b/lang/id_ID.po similarity index 100% rename from owncloudorgnew/lang/id_ID.po rename to lang/id_ID.po diff --git a/owncloudorgnew/lang/it_IT.mo b/lang/it_IT.mo similarity index 100% rename from owncloudorgnew/lang/it_IT.mo rename to lang/it_IT.mo diff --git a/owncloudorgnew/lang/it_IT.po b/lang/it_IT.po similarity index 100% rename from owncloudorgnew/lang/it_IT.po rename to lang/it_IT.po diff --git a/owncloudorgnew/lang/ko_KR.mo b/lang/ko_KR.mo similarity index 100% rename from owncloudorgnew/lang/ko_KR.mo rename to lang/ko_KR.mo diff --git a/owncloudorgnew/lang/ko_KR.po b/lang/ko_KR.po similarity index 100% rename from owncloudorgnew/lang/ko_KR.po rename to lang/ko_KR.po diff --git a/owncloudorgnew/lang/mk_MK.mo b/lang/mk_MK.mo similarity index 100% rename from owncloudorgnew/lang/mk_MK.mo rename to lang/mk_MK.mo diff --git a/owncloudorgnew/lang/mk_MK.po b/lang/mk_MK.po similarity index 100% rename from owncloudorgnew/lang/mk_MK.po rename to lang/mk_MK.po diff --git a/owncloudorgnew/lang/ms_MY.mo b/lang/ms_MY.mo similarity index 100% rename from owncloudorgnew/lang/ms_MY.mo rename to lang/ms_MY.mo diff --git a/owncloudorgnew/lang/ms_MY.po b/lang/ms_MY.po similarity index 100% rename from owncloudorgnew/lang/ms_MY.po rename to lang/ms_MY.po diff --git a/owncloudorgnew/lang/nb_NO.mo b/lang/nb_NO.mo similarity index 100% rename from owncloudorgnew/lang/nb_NO.mo rename to lang/nb_NO.mo diff --git a/owncloudorgnew/lang/nb_NO.po b/lang/nb_NO.po similarity index 100% rename from owncloudorgnew/lang/nb_NO.po rename to lang/nb_NO.po diff --git a/owncloudorgnew/lang/nl_NL.mo b/lang/nl_NL.mo similarity index 100% rename from owncloudorgnew/lang/nl_NL.mo rename to lang/nl_NL.mo diff --git a/owncloudorgnew/lang/nl_NL.po b/lang/nl_NL.po similarity index 100% rename from owncloudorgnew/lang/nl_NL.po rename to lang/nl_NL.po diff --git a/owncloudorgnew/lang/nn_NO.mo b/lang/nn_NO.mo similarity index 100% rename from owncloudorgnew/lang/nn_NO.mo rename to lang/nn_NO.mo diff --git a/owncloudorgnew/lang/nn_NO.po b/lang/nn_NO.po similarity index 100% rename from owncloudorgnew/lang/nn_NO.po rename to lang/nn_NO.po diff --git a/owncloudorgnew/lang/pl_PL.mo b/lang/pl_PL.mo similarity index 100% rename from owncloudorgnew/lang/pl_PL.mo rename to lang/pl_PL.mo diff --git a/owncloudorgnew/lang/pl_PL.po b/lang/pl_PL.po similarity index 100% rename from owncloudorgnew/lang/pl_PL.po rename to lang/pl_PL.po diff --git a/owncloudorgnew/lang/pt_BR.mo b/lang/pt_BR.mo similarity index 100% rename from owncloudorgnew/lang/pt_BR.mo rename to lang/pt_BR.mo diff --git a/owncloudorgnew/lang/pt_BR.po b/lang/pt_BR.po similarity index 100% rename from owncloudorgnew/lang/pt_BR.po rename to lang/pt_BR.po diff --git a/owncloudorgnew/lang/ro_RO.mo b/lang/ro_RO.mo similarity index 100% rename from owncloudorgnew/lang/ro_RO.mo rename to lang/ro_RO.mo diff --git a/owncloudorgnew/lang/ro_RO.po b/lang/ro_RO.po similarity index 100% rename from owncloudorgnew/lang/ro_RO.po rename to lang/ro_RO.po diff --git a/owncloudorgnew/lang/roots.pot b/lang/roots.pot similarity index 100% rename from owncloudorgnew/lang/roots.pot rename to lang/roots.pot diff --git a/owncloudorgnew/lang/ru_RU.mo b/lang/ru_RU.mo similarity index 100% rename from owncloudorgnew/lang/ru_RU.mo rename to lang/ru_RU.mo diff --git a/owncloudorgnew/lang/ru_RU.po b/lang/ru_RU.po similarity index 100% rename from owncloudorgnew/lang/ru_RU.po rename to lang/ru_RU.po diff --git a/owncloudorgnew/lang/sr_RS.mo b/lang/sr_RS.mo similarity index 100% rename from owncloudorgnew/lang/sr_RS.mo rename to lang/sr_RS.mo diff --git a/owncloudorgnew/lang/sr_RS.pot b/lang/sr_RS.pot similarity index 100% rename from owncloudorgnew/lang/sr_RS.pot rename to lang/sr_RS.pot diff --git a/owncloudorgnew/lang/sv_SE.mo b/lang/sv_SE.mo similarity index 100% rename from owncloudorgnew/lang/sv_SE.mo rename to lang/sv_SE.mo diff --git a/owncloudorgnew/lang/sv_SE.po b/lang/sv_SE.po similarity index 100% rename from owncloudorgnew/lang/sv_SE.po rename to lang/sv_SE.po diff --git a/owncloudorgnew/lang/tr_TR.mo b/lang/tr_TR.mo similarity index 100% rename from owncloudorgnew/lang/tr_TR.mo rename to lang/tr_TR.mo diff --git a/owncloudorgnew/lang/tr_TR.po b/lang/tr_TR.po similarity index 100% rename from owncloudorgnew/lang/tr_TR.po rename to lang/tr_TR.po diff --git a/owncloudorgnew/lang/vi_VN.mo b/lang/vi_VN.mo similarity index 100% rename from owncloudorgnew/lang/vi_VN.mo rename to lang/vi_VN.mo diff --git a/owncloudorgnew/lang/vi_VN.po b/lang/vi_VN.po similarity index 100% rename from owncloudorgnew/lang/vi_VN.po rename to lang/vi_VN.po diff --git a/owncloudorgnew/lang/zh_CN.mo b/lang/zh_CN.mo similarity index 100% rename from owncloudorgnew/lang/zh_CN.mo rename to lang/zh_CN.mo diff --git a/owncloudorgnew/lang/zh_CN.po b/lang/zh_CN.po similarity index 100% rename from owncloudorgnew/lang/zh_CN.po rename to lang/zh_CN.po diff --git a/owncloudorgnew/lang/zh_TW.mo b/lang/zh_TW.mo similarity index 100% rename from owncloudorgnew/lang/zh_TW.mo rename to lang/zh_TW.mo diff --git a/owncloudorgnew/lang/zh_TW.po b/lang/zh_TW.po similarity index 100% rename from owncloudorgnew/lang/zh_TW.po rename to lang/zh_TW.po diff --git a/owncloudorgnew/lib/activation.php b/lib/activation.php similarity index 100% rename from owncloudorgnew/lib/activation.php rename to lib/activation.php diff --git a/owncloudorgnew/lib/cleanup.php b/lib/cleanup.php similarity index 100% rename from owncloudorgnew/lib/cleanup.php rename to lib/cleanup.php diff --git a/owncloudorgnew/lib/comments.php b/lib/comments.php similarity index 100% rename from owncloudorgnew/lib/comments.php rename to lib/comments.php diff --git a/owncloudorgnew/lib/config.php b/lib/config.php similarity index 100% rename from owncloudorgnew/lib/config.php rename to lib/config.php diff --git a/owncloudorgnew/lib/custom.php b/lib/custom.php similarity index 100% rename from owncloudorgnew/lib/custom.php rename to lib/custom.php diff --git a/owncloudorgnew/lib/gallery.php b/lib/gallery.php similarity index 100% rename from owncloudorgnew/lib/gallery.php rename to lib/gallery.php diff --git a/owncloudorgnew/lib/init.php b/lib/init.php similarity index 100% rename from owncloudorgnew/lib/init.php rename to lib/init.php diff --git a/owncloudorgnew/lib/nav.php b/lib/nav.php similarity index 100% rename from owncloudorgnew/lib/nav.php rename to lib/nav.php diff --git a/owncloudorgnew/lib/recentblogswidget.php b/lib/recentblogswidget.php similarity index 100% rename from owncloudorgnew/lib/recentblogswidget.php rename to lib/recentblogswidget.php diff --git a/owncloudorgnew/lib/recentdocswidget.php b/lib/recentdocswidget.php similarity index 100% rename from owncloudorgnew/lib/recentdocswidget.php rename to lib/recentdocswidget.php diff --git a/owncloudorgnew/lib/relative-urls.php b/lib/relative-urls.php similarity index 100% rename from owncloudorgnew/lib/relative-urls.php rename to lib/relative-urls.php diff --git a/owncloudorgnew/lib/scripts.php b/lib/scripts.php similarity index 100% rename from owncloudorgnew/lib/scripts.php rename to lib/scripts.php diff --git a/owncloudorgnew/lib/sidebar.php b/lib/sidebar.php similarity index 100% rename from owncloudorgnew/lib/sidebar.php rename to lib/sidebar.php diff --git a/owncloudorgnew/lib/titles.php b/lib/titles.php similarity index 100% rename from owncloudorgnew/lib/titles.php rename to lib/titles.php diff --git a/owncloudorgnew/lib/utils.php b/lib/utils.php similarity index 100% rename from owncloudorgnew/lib/utils.php rename to lib/utils.php diff --git a/owncloudorgnew/lib/widgets.php b/lib/widgets.php similarity index 100% rename from owncloudorgnew/lib/widgets.php rename to lib/widgets.php diff --git a/owncloudorgnew/lib/wrapper.php b/lib/wrapper.php similarity index 100% rename from owncloudorgnew/lib/wrapper.php rename to lib/wrapper.php diff --git a/owncloudorgnew/.jshintrc b/node_modules/grunt-contrib-clean/.jshintrc similarity index 56% rename from owncloudorgnew/.jshintrc rename to node_modules/grunt-contrib-clean/.jshintrc index 136eae537..6b4c1a9b1 100644 --- a/owncloudorgnew/.jshintrc +++ b/node_modules/grunt-contrib-clean/.jshintrc @@ -1,16 +1,14 @@ { - "bitwise": true, - "browser": true, "curly": true, "eqeqeq": true, - "eqnull": true, - "esnext": true, "immed": true, - "jquery": true, "latedef": true, "newcap": true, "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, "node": true, - "strict": false, - "trailing": true + "es5": true } diff --git a/node_modules/grunt-contrib-clean/.npmignore b/node_modules/grunt-contrib-clean/.npmignore new file mode 100644 index 000000000..5cb6bfd4d --- /dev/null +++ b/node_modules/grunt-contrib-clean/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp \ No newline at end of file diff --git a/node_modules/grunt-contrib-clean/.travis.yml b/node_modules/grunt-contrib-clean/.travis.yml new file mode 100644 index 000000000..57661910e --- /dev/null +++ b/node_modules/grunt-contrib-clean/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-clean/AUTHORS b/node_modules/grunt-contrib-clean/AUTHORS new file mode 100644 index 000000000..393d81454 --- /dev/null +++ b/node_modules/grunt-contrib-clean/AUTHORS @@ -0,0 +1,6 @@ +Tim Branyen (http://tbranyen.com/) +Tyler Kellen (http://goingslowly.com/) +Chris Talkington (http://christalkington.com/) +Sebastian Golasch (http://www.asciidisco.com/) +Vlad Filippov (http://vf.io) +"Cowboy" Ben Alman (http://benalman.com/) diff --git a/node_modules/grunt-contrib-clean/CHANGELOG b/node_modules/grunt-contrib-clean/CHANGELOG new file mode 100644 index 000000000..06c16031c --- /dev/null +++ b/node_modules/grunt-contrib-clean/CHANGELOG @@ -0,0 +1,37 @@ +v0.5.0: + date: 2013-07-15 + changes: + - Use rimraf directly, version 2.2.1 to fix issue on Windows. + - Add no-write option to mimic grunt.file.delete behavior. +v0.4.1: + date: 2013-04-16 + changes: + - Check if file exists to avoid trying to delete a non-existent file. +v0.4.0: + date: 2013-02-15 + changes: + - First official release for Grunt 0.4.0. +v0.4.0rc6: + date: 2013-01-18 + changes: + - Updating grunt/gruntplugin dependencies to rc6. + - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. +v0.4.0rc5: + date: 2013-01-09 + changes: + - Updating to work with grunt v0.4.0rc5. + - Switching to this.filesSrc api. +v0.4.0a: + date: 2012-12-07 + changes: + - Conversion to grunt v0.4 conventions. + - Remove node v0.6 and grunt v0.3 support. + - Add force option to bypass CWD check. +v0.3.0: + date: 2012-09-23 + changes: + - Options no longer accepted from global config key. +v0.2.0: + date: 2012-09-10 + changes: + - Refactored from grunt-contrib into individual repo. diff --git a/node_modules/grunt-contrib-clean/CONTRIBUTING.md b/node_modules/grunt-contrib-clean/CONTRIBUTING.md new file mode 100644 index 000000000..5d08cc387 --- /dev/null +++ b/node_modules/grunt-contrib-clean/CONTRIBUTING.md @@ -0,0 +1 @@ +Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project. diff --git a/node_modules/grunt-contrib-clean/Gruntfile.js b/node_modules/grunt-contrib-clean/Gruntfile.js new file mode 100644 index 000000000..79adb0032 --- /dev/null +++ b/node_modules/grunt-contrib-clean/Gruntfile.js @@ -0,0 +1,60 @@ +/* + * grunt-contrib-clean + * http://gruntjs.com/ + * + * Copyright (c) 2013 Tim Branyen, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'tasks/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + }, + }, + + // Configuration to be run (and then tested). + clean: { + short: ['tmp/sample_short'], + long: { + src: ['tmp/sample_long'], + }, + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'], + }, + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-internal'); + + // Setup a test helper to create some folders to clean. + grunt.registerTask('copy', 'Copy fixtures to a temp location.', function() { + grunt.file.copy('test/fixtures/sample_long/long.txt', 'tmp/sample_long/long.txt'); + grunt.file.copy('test/fixtures/sample_short/short.txt', 'tmp/sample_short/short.txt'); + }); + + // Whenever the 'test' task is run, first create some files to be cleaned, + // then run this plugin's task(s), then test the result. + grunt.registerTask('test', ['copy', 'clean', 'nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test', 'build-contrib']); +}; diff --git a/node_modules/grunt-contrib-clean/LICENSE-MIT b/node_modules/grunt-contrib-clean/LICENSE-MIT new file mode 100644 index 000000000..9bf64d19c --- /dev/null +++ b/node_modules/grunt-contrib-clean/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Tim Branyen, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-clean/README.md b/node_modules/grunt-contrib-clean/README.md new file mode 100644 index 000000000..ad90e0d64 --- /dev/null +++ b/node_modules/grunt-contrib-clean/README.md @@ -0,0 +1,90 @@ +# grunt-contrib-clean [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-clean.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-clean) + +> Clean files and folders. + + + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-contrib-clean --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-contrib-clean'); +``` + +*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-clean/tree/grunt-0.3-stable).* + + + +## Clean task +_Run this task with the `grunt clean` command._ + +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. + +*Due to the destructive nature of this task, always be cautious of the paths you clean.* +### Options + +#### force +Type: `Boolean` +Default: false + +This overrides this task from blocking deletion of folders outside current working dir (CWD). Use with caution. + +#### no-write +Type: `Boolean` +Default: false + +Will log messages of what would happen if the task was ran but doesn't actually delete the files. + +### Usage Examples + +There are three formats you can use to run this task. + +#### Short + +```js +clean: ["path/to/dir/one", "path/to/dir/two"] +``` + +#### Medium (specific targets with global options) + +```js +clean: { + build: ["path/to/dir/one", "path/to/dir/two"], + release: ["path/to/another/dir/one", "path/to/another/dir/two"] +}, +``` + +#### Long (specific targets with per target options) + +```js +clean: { + build: { + src: ["path/to/dir/one", "path/to/dir/two"] + } +} +``` + +## Release History + + * 2013-07-15   v0.5.0   Use rimraf directly, version 2.2.1 to fix issue on Windows. Add no-write option to mimic grunt.file.delete behavior. + * 2013-04-16   v0.4.1   Check if file exists to avoid trying to delete a non-existent file. + * 2013-02-15   v0.4.0   First official release for Grunt 0.4.0. + * 2013-01-18   v0.4.0rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. + * 2013-01-09   v0.4.0rc5   Updating to work with grunt v0.4.0rc5. Switching to this.filesSrc api. + * 2012-12-07   v0.4.0a   Conversion to grunt v0.4 conventions. Remove node v0.6 and grunt v0.3 support. Add force option to bypass CWD check. + * 2012-09-23   v0.3.0   Options no longer accepted from global config key. + * 2012-09-10   v0.2.0   Refactored from grunt-contrib into individual repo. + +--- + +Task submitted by [Tim Branyen](http://tbranyen.com/) + +*This file was generated on Mon Jul 15 2013 20:45:46.* diff --git a/node_modules/grunt-contrib-clean/docs/clean-examples.md b/node_modules/grunt-contrib-clean/docs/clean-examples.md new file mode 100644 index 000000000..267aea743 --- /dev/null +++ b/node_modules/grunt-contrib-clean/docs/clean-examples.md @@ -0,0 +1,28 @@ +# Usage Examples + +There are three formats you can use to run this task. + +## Short + +```js +clean: ["path/to/dir/one", "path/to/dir/two"] +``` + +## Medium (specific targets with global options) + +```js +clean: { + build: ["path/to/dir/one", "path/to/dir/two"], + release: ["path/to/another/dir/one", "path/to/another/dir/two"] +}, +``` + +## Long (specific targets with per target options) + +```js +clean: { + build: { + src: ["path/to/dir/one", "path/to/dir/two"] + } +} +``` \ No newline at end of file diff --git a/node_modules/grunt-contrib-clean/docs/clean-options.md b/node_modules/grunt-contrib-clean/docs/clean-options.md new file mode 100644 index 000000000..a8d412a79 --- /dev/null +++ b/node_modules/grunt-contrib-clean/docs/clean-options.md @@ -0,0 +1,13 @@ +# Options + +## force +Type: `Boolean` +Default: false + +This overrides this task from blocking deletion of folders outside current working dir (CWD). Use with caution. + +## no-write +Type: `Boolean` +Default: false + +Will log messages of what would happen if the task was ran but doesn't actually delete the files. diff --git a/node_modules/grunt-contrib-clean/docs/clean-overview.md b/node_modules/grunt-contrib-clean/docs/clean-overview.md new file mode 100644 index 000000000..62f836580 --- /dev/null +++ b/node_modules/grunt-contrib-clean/docs/clean-overview.md @@ -0,0 +1,3 @@ +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. + +*Due to the destructive nature of this task, always be cautious of the paths you clean.* \ No newline at end of file diff --git a/node_modules/grunt-contrib-clean/docs/overview.md b/node_modules/grunt-contrib-clean/docs/overview.md new file mode 100644 index 000000000..d8014b616 --- /dev/null +++ b/node_modules/grunt-contrib-clean/docs/overview.md @@ -0,0 +1 @@ +*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-clean/tree/grunt-0.3-stable).* diff --git a/node_modules/grunt-contrib-clean/node_modules/.bin/rimraf b/node_modules/grunt-contrib-clean/node_modules/.bin/rimraf new file mode 120000 index 000000000..4cd49a49d --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/.bin/rimraf @@ -0,0 +1 @@ +../rimraf/bin.js \ No newline at end of file diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/AUTHORS b/node_modules/grunt-contrib-clean/node_modules/rimraf/AUTHORS new file mode 100644 index 000000000..247b75437 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/AUTHORS @@ -0,0 +1,6 @@ +# Authors sorted by whether or not they're me. +Isaac Z. Schlueter (http://blog.izs.me) +Wayne Larsen (http://github.com/wvl) +ritch +Marcel Laverdet +Yosef Dinerstein diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/LICENSE b/node_modules/grunt-contrib-clean/node_modules/rimraf/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/README.md b/node_modules/grunt-contrib-clean/node_modules/rimraf/README.md new file mode 100644 index 000000000..8fc677956 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/README.md @@ -0,0 +1,26 @@ +A `rm -rf` for node. + +Install with `npm install rimraf`, or just drop rimraf.js somewhere. + +## API + +`rimraf(f, callback)` + +The callback will be called with an error if there is one. Certain +errors are handled for you: + +* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times + before giving up. +* `EMFILE` - If too many file descriptors get opened, rimraf will + patiently wait until more become available. + + +## rimraf.sync + +It can remove stuff synchronously, too. But that's not so good. Use +the async API. It's better. + +## CLI + +If installed with `npm install rimraf -g` it can be used as a global +command `rimraf ` which is useful for cross platform support. diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/bin.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/bin.js new file mode 100755 index 000000000..29bfa8a63 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/bin.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +var rimraf = require('./') + +var help = false +var dashdash = false +var args = process.argv.slice(2).filter(function(arg) { + if (dashdash) + return !!arg + else if (arg === '--') + dashdash = true + else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/)) + help = true + else + return !!arg +}); + +if (help || args.length === 0) { + // If they didn't ask for help, then this is not a "success" + var log = help ? console.log : console.error + log('Usage: rimraf ') + log('') + log(' Deletes all files and folders at "path" recursively.') + log('') + log('Options:') + log('') + log(' -h, --help Display this usage info') + process.exit(help ? 0 : 1) +} else { + args.forEach(function(arg) { + rimraf.sync(arg) + }) +} diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/.npmignore b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/.npmignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/LICENSE b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/README.md b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/README.md new file mode 100644 index 000000000..eb1a10935 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/README.md @@ -0,0 +1,26 @@ +# graceful-fs + +graceful-fs functions as a drop-in replacement for the fs module, +making various improvements. + +The improvements are meant to normalize behavior across different +platforms and environments, and to make filesystem access more +resilient to errors. + +## Improvements over fs module + +graceful-fs: + +* Queues up `open` and `readdir` calls, and retries them once + something closes if there is an EMFILE error from too many file + descriptors. +* fixes `lchmod` for Node versions prior to 0.6.2. +* implements `fs.lutimes` if possible. Otherwise it becomes a noop. +* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or + `lchown` if the user isn't root. +* makes `lchmod` and `lchown` become noops, if not available. +* retries reading a file if `read` results in EAGAIN error. + +On Windows, it retries renaming a file for up to one second if `EACCESS` +or `EPERM` error occurs, likely because antivirus software has locked +the directory. diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 000000000..1865f92cc --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js @@ -0,0 +1,159 @@ +// Monkey-patching the fs module. +// It's ugly, but there is simply no other way to do this. +var fs = module.exports = require('fs') + +var assert = require('assert') + +// fix up some busted stuff, mostly on windows and old nodes +require('./polyfills.js') + +// The EMFILE enqueuing stuff + +var util = require('util') + +function noop () {} + +var debug = noop +var util = require('util') +if (util.debuglog) + debug = util.debuglog('gfs') +else if (/\bgfs\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS: ' + m.split(/\n/).join('\nGFS: ') + console.error(m) + } + +if (/\bgfs\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug('fds', fds) + debug(queue) + assert.equal(queue.length, 0) + }) +} + + +var originalOpen = fs.open +fs.open = open + +function open(path, flags, mode, cb) { + if (typeof mode === "function") cb = mode, mode = null + if (typeof cb !== "function") cb = noop + new OpenReq(path, flags, mode, cb) +} + +function OpenReq(path, flags, mode, cb) { + this.path = path + this.flags = flags + this.mode = mode + this.cb = cb + Req.call(this) +} + +util.inherits(OpenReq, Req) + +OpenReq.prototype.process = function() { + originalOpen.call(fs, this.path, this.flags, this.mode, this.done) +} + +var fds = {} +OpenReq.prototype.done = function(er, fd) { + debug('open done', er, fd) + if (fd) + fds['fd' + fd] = this.path + Req.prototype.done.call(this, er, fd) +} + + +var originalReaddir = fs.readdir +fs.readdir = readdir + +function readdir(path, cb) { + if (typeof cb !== "function") cb = noop + new ReaddirReq(path, cb) +} + +function ReaddirReq(path, cb) { + this.path = path + this.cb = cb + Req.call(this) +} + +util.inherits(ReaddirReq, Req) + +ReaddirReq.prototype.process = function() { + originalReaddir.call(fs, this.path, this.done) +} + +ReaddirReq.prototype.done = function(er, files) { + Req.prototype.done.call(this, er, files) + onclose() +} + + +var originalClose = fs.close +fs.close = close + +function close (fd, cb) { + debug('close', fd) + if (typeof cb !== "function") cb = noop + delete fds['fd' + fd] + originalClose.call(fs, fd, function(er) { + onclose() + cb(er) + }) +} + + +var originalCloseSync = fs.closeSync +fs.closeSync = closeSync + +function closeSync (fd) { + try { + return originalCloseSync(fd) + } finally { + onclose() + } +} + + +// Req class +function Req () { + // start processing + this.done = this.done.bind(this) + this.failures = 0 + this.process() +} + +Req.prototype.done = function (er, result) { + var tryAgain = false + if (er) { + var code = er.code + var tryAgain = code === "EMFILE" + if (process.platform === "win32") + tryAgain = tryAgain || code === "OK" + } + + if (tryAgain) { + this.failures ++ + enqueue(this) + } else { + var cb = this.cb + cb(er, result) + } +} + +var queue = [] + +function enqueue(req) { + queue.push(req) + debug('enqueue %d %s', queue.length, req.constructor.name, req) +} + +function onclose() { + var req = queue.shift() + if (req) { + debug('process', req.constructor.name, req) + req.process() + } +} diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/package.json b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/package.json new file mode 100644 index 000000000..69706eb05 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/package.json @@ -0,0 +1,52 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "graceful-fs", + "description": "A drop-in replacement for fs, making various improvements.", + "version": "2.0.1", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-graceful-fs.git" + }, + "main": "graceful-fs.js", + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "keywords": [ + "fs", + "module", + "reading", + "retry", + "retries", + "queue", + "error", + "errors", + "handling", + "EMFILE", + "EAGAIN", + "EINVAL", + "EPERM", + "EACCESS" + ], + "license": "BSD", + "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* Queues up `open` and `readdir` calls, and retries them once\n something closes if there is an EMFILE error from too many file\n descriptors.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-graceful-fs/issues" + }, + "_id": "graceful-fs@2.0.1", + "dist": { + "shasum": "38a8f3a63c7d6b7e272eedb0abef5862da2fbd43" + }, + "_from": "graceful-fs@~2", + "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.1.tgz" +} diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/polyfills.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/polyfills.js new file mode 100644 index 000000000..afc83b3f2 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/polyfills.js @@ -0,0 +1,228 @@ +var fs = require('fs') +var constants = require('constants') + +var origCwd = process.cwd +var cwd = null +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +var chdir = process.chdir +process.chdir = function(d) { + cwd = null + chdir.call(process, d) +} + +// (re-)implement some things that are known busted or missing. + +// lchmod, broken prior to 0.6.2 +// back-port the fix here. +if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + fs.lchmod = function (path, mode, callback) { + callback = callback || noop + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var err, err2 + try { + var ret = fs.fchmodSync(fd, mode) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } +} + + +// lutimes implementation, or no-op +if (!fs.lutimes) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + cb = cb || noop + if (er) return cb(er) + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + return cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + , err + , err2 + , ret + + try { + var ret = fs.futimesSync(fd, at, mt) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } + + } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) { + // maybe utimensat will be bound soonish? + fs.lutimes = function (path, at, mt, cb) { + fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb) + } + + fs.lutimesSync = function (path, at, mt) { + return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW) + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) } + fs.lutimesSync = function () {} + } +} + + +// https://github.com/isaacs/node-graceful-fs/issues/4 +// Chown should not fail on einval or eperm if non-root. + +fs.chown = chownFix(fs.chown) +fs.fchown = chownFix(fs.fchown) +fs.lchown = chownFix(fs.lchown) + +fs.chownSync = chownFixSync(fs.chownSync) +fs.fchownSync = chownFixSync(fs.fchownSync) +fs.lchownSync = chownFixSync(fs.lchownSync) + +function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er, res) { + if (chownErOk(er)) er = null + cb(er, res) + }) + } +} + +function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + +function chownErOk (er) { + // if there's no getuid, or if getuid() is something other than 0, + // and the error is EINVAL or EPERM, then just ignore it. + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // When running as root, or if other types of errors are encountered, + // then it's strict. + if (!er || (!process.getuid || process.getuid() !== 0) + && (er.code === "EINVAL" || er.code === "EPERM")) return true +} + + +// if lchmod/lchown do not exist, then make them no-ops +if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + process.nextTick(cb) + } + fs.lchmodSync = function () {} +} +if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + process.nextTick(cb) + } + fs.lchownSync = function () {} +} + + + +// on Windows, A/V software can lock the directory, causing this +// to fail with an EACCES or EPERM if the directory contains newly +// created files. Try again on failure, for up to 1 second. +if (process.platform === "win32") { + var rename_ = fs.rename + fs.rename = function rename (from, to, cb) { + var start = Date.now() + rename_(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 1000) { + return rename_(from, to, CB) + } + cb(er) + }) + } +} + + +// if read() returns EAGAIN, then just try it again. +var read = fs.read +fs.read = function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return read.call(fs, fd, buffer, offset, length, position, callback) +} + +var readSync = fs.readSync +fs.readSync = function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } +} + diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/test/open.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/test/open.js new file mode 100644 index 000000000..104f36b0b --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs/test/open.js @@ -0,0 +1,39 @@ +var test = require('tap').test +var fs = require('../graceful-fs.js') + +test('graceful fs is monkeypatched fs', function (t) { + t.equal(fs, require('fs')) + t.end() +}) + +test('open an existing file works', function (t) { + var fd = fs.openSync(__filename, 'r') + fs.closeSync(fd) + fs.open(__filename, 'r', function (er, fd) { + if (er) throw er + fs.close(fd, function (er) { + if (er) throw er + t.pass('works') + t.end() + }) + }) +}) + +test('open a non-existing file throws', function (t) { + var er + try { + var fd = fs.openSync('this file does not exist', 'r') + } catch (x) { + er = x + } + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + + fs.open('neither does this file', 'r', function (er, fd) { + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + t.end() + }) +}) diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/package.json b/node_modules/grunt-contrib-clean/node_modules/rimraf/package.json new file mode 100644 index 000000000..24db94f38 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/package.json @@ -0,0 +1,65 @@ +{ + "name": "rimraf", + "version": "2.2.2", + "main": "rimraf.js", + "description": "A deep deletion module for node (like `rm -rf`)", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/rimraf/raw/master/LICENSE" + }, + "optionalDependencies": { + "graceful-fs": "~2" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/rimraf.git" + }, + "scripts": { + "test": "cd test && bash run.sh" + }, + "bin": { + "rimraf": "./bin.js" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + { + "name": "Wayne Larsen", + "email": "wayne@larsen.st", + "url": "http://github.com/wvl" + }, + { + "name": "ritch", + "email": "skawful@gmail.com" + }, + { + "name": "Marcel Laverdet" + }, + { + "name": "Yosef Dinerstein", + "email": "yosefd@microsoft.com" + } + ], + "readme": "A `rm -rf` for node.\n\nInstall with `npm install rimraf`, or just drop rimraf.js somewhere.\n\n## API\n\n`rimraf(f, callback)`\n\nThe callback will be called with an error if there is one. Certain\nerrors are handled for you:\n\n* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times\n before giving up.\n* `EMFILE` - If too many file descriptors get opened, rimraf will\n patiently wait until more become available.\n\n\n## rimraf.sync\n\nIt can remove stuff synchronously, too. But that's not so good. Use\nthe async API. It's better.\n\n## CLI\n\nIf installed with `npm install rimraf -g` it can be used as a global\ncommand `rimraf ` which is useful for cross platform support.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/rimraf/issues" + }, + "dependencies": { + "graceful-fs": "~2" + }, + "_id": "rimraf@2.2.2", + "dist": { + "shasum": "345f45954394b40790333b3ff1b46a8e78b693be" + }, + "_from": "rimraf@~2.2.1", + "_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.2.tgz" +} diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/rimraf.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/rimraf.js new file mode 100644 index 000000000..55f8d9a48 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/rimraf.js @@ -0,0 +1,184 @@ +module.exports = rimraf +rimraf.sync = rimrafSync + +var path = require("path") + , fs + +try { + // optional dependency + fs = require("graceful-fs") +} catch (er) { + fs = require("fs") +} + +// for EMFILE handling +var timeout = 0 +exports.EMFILE_MAX = 1000 +exports.BUSYTRIES_MAX = 3 + +var isWindows = (process.platform === "win32") + +function rimraf (p, cb) { + if (!cb) throw new Error("No callback passed to rimraf()") + + var busyTries = 0 + rimraf_(p, function CB (er) { + if (er) { + if (er.code === "EBUSY" && busyTries < exports.BUSYTRIES_MAX) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, CB) + }, time) + } + + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) { + return setTimeout(function () { + rimraf_(p, CB) + }, timeout ++) + } + + // already gone + if (er.code === "ENOENT") er = null + } + + timeout = 0 + cb(er) + }) +} + +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +function rimraf_ (p, cb) { + fs.unlink(p, function (er) { + if (er) { + if (er.code === "ENOENT") + return cb() + if (er.code === "EPERM") + return (isWindows) ? fixWinEPERM(p, er, cb) : rmdir(p, er, cb) + if (er.code === "EISDIR") + return rmdir(p, er, cb) + } + return cb(er) + }) +} + +function fixWinEPERM (p, er, cb) { + fs.chmod(p, 666, function (er2) { + if (er2) + cb(er2.code === "ENOENT" ? null : er) + else + fs.stat(p, function(er3, stats) { + if (er3) + cb(er3.code === "ENOENT" ? null : er) + else if (stats.isDirectory()) + rmdir(p, er, cb) + else + fs.unlink(p, cb) + }) + }) +} + +function fixWinEPERMSync (p, er, cb) { + try { + fs.chmodSync(p, 666) + } catch (er2) { + if (er2.code !== "ENOENT") + throw er + } + + try { + var stats = fs.statSync(p) + } catch (er3) { + if (er3 !== "ENOENT") + throw er + } + + if (stats.isDirectory()) + rmdirSync(p, er) + else + fs.unlinkSync(p) +} + +function rmdir (p, originalEr, cb) { + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + fs.rmdir(p, function (er) { + if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST")) + rmkids(p, cb) + else if (er && er.code === "ENOTDIR") + cb(originalEr) + else + cb(er) + }) +} + +function rmkids(p, cb) { + fs.readdir(p, function (er, files) { + if (er) + return cb(er) + var n = files.length + if (n === 0) + return fs.rmdir(p, cb) + var errState + files.forEach(function (f) { + rimraf(path.join(p, f), function (er) { + if (errState) + return + if (er) + return cb(errState = er) + if (--n === 0) + fs.rmdir(p, cb) + }) + }) + }) +} + +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +function rimrafSync (p) { + try { + fs.unlinkSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "EPERM") + return isWindows ? fixWinEPERMSync(p, er) : rmdirSync(p, er) + if (er.code !== "EISDIR") + throw er + rmdirSync(p, er) + } +} + +function rmdirSync (p, originalEr) { + try { + fs.rmdirSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "ENOTDIR") + throw originalEr + if (er.code === "ENOTEMPTY" || er.code === "EEXIST") + rmkidsSync(p) + } +} + +function rmkidsSync (p) { + fs.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f)) + }) + fs.rmdirSync(p) +} diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/test/run.sh b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/run.sh new file mode 100644 index 000000000..598f0163b --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e +for i in test-*.js; do + echo -n $i ... + bash setup.sh + node $i + ! [ -d target ] + echo "pass" +done +rm -rf target diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/test/setup.sh b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/setup.sh new file mode 100644 index 000000000..2602e6316 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/setup.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -e + +files=10 +folders=2 +depth=4 +target="$PWD/target" + +rm -rf target + +fill () { + local depth=$1 + local files=$2 + local folders=$3 + local target=$4 + + if ! [ -d $target ]; then + mkdir -p $target + fi + + local f + + f=$files + while [ $f -gt 0 ]; do + touch "$target/f-$depth-$f" + let f-- + done + + let depth-- + + if [ $depth -le 0 ]; then + return 0 + fi + + f=$folders + while [ $f -gt 0 ]; do + mkdir "$target/folder-$depth-$f" + fill $depth $files $folders "$target/d-$depth-$f" + let f-- + done +} + +fill $depth $files $folders $target + +# sanity assert +[ -d $target ] diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-async.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-async.js new file mode 100644 index 000000000..9c2e0b7be --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-async.js @@ -0,0 +1,5 @@ +var rimraf = require("../rimraf") + , path = require("path") +rimraf(path.join(__dirname, "target"), function (er) { + if (er) throw er +}) diff --git a/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-sync.js b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-sync.js new file mode 100644 index 000000000..eb71f1047 --- /dev/null +++ b/node_modules/grunt-contrib-clean/node_modules/rimraf/test/test-sync.js @@ -0,0 +1,3 @@ +var rimraf = require("../rimraf") + , path = require("path") +rimraf.sync(path.join(__dirname, "target")) diff --git a/node_modules/grunt-contrib-clean/package.json b/node_modules/grunt-contrib-clean/package.json new file mode 100644 index 000000000..867e6cded --- /dev/null +++ b/node_modules/grunt-contrib-clean/package.json @@ -0,0 +1,79 @@ +{ + "name": "grunt-contrib-clean", + "description": "Clean files and folders.", + "version": "0.5.0", + "homepage": "https://github.com/gruntjs/grunt-contrib-clean", + "author": { + "name": "Grunt Team", + "url": "http://gruntjs.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/gruntjs/grunt-contrib-clean.git" + }, + "bugs": { + "url": "https://github.com/gruntjs/grunt-contrib-clean/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/gruntjs/grunt-contrib-clean/blob/master/LICENSE-MIT" + } + ], + "main": "Gruntfile.js", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "rimraf": "~2.2.1" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.2.0", + "grunt-contrib-nodeunit": "~0.1.2", + "grunt-contrib-internal": "~0.4.4", + "grunt": "~0.4.0" + }, + "peerDependencies": { + "grunt": "~0.4.0" + }, + "keywords": [ + "gruntplugin" + ], + "contributors": [ + { + "name": "Tim Branyen", + "url": "http://tbranyen.com/" + }, + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com/" + }, + { + "name": "Chris Talkington", + "url": "http://christalkington.com/" + }, + { + "name": "Sebastian Golasch", + "url": "http://www.asciidisco.com/" + }, + { + "name": "Vlad Filippov", + "url": "http://vf.io" + }, + { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + } + ], + "readme": "# grunt-contrib-clean [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-clean.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-clean)\n\n> Clean files and folders.\n\n\n\n## Getting Started\nThis plugin requires Grunt `~0.4.0`\n\nIf you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:\n\n```shell\nnpm install grunt-contrib-clean --save-dev\n```\n\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\n\n```js\ngrunt.loadNpmTasks('grunt-contrib-clean');\n```\n\n*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-clean/tree/grunt-0.3-stable).*\n\n\n\n## Clean task\n_Run this task with the `grunt clean` command._\n\nTask targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide.\n\n*Due to the destructive nature of this task, always be cautious of the paths you clean.*\n### Options\n\n#### force\nType: `Boolean` \nDefault: false\n\nThis overrides this task from blocking deletion of folders outside current working dir (CWD). Use with caution.\n\n#### no-write\nType: `Boolean` \nDefault: false\n\nWill log messages of what would happen if the task was ran but doesn't actually delete the files.\n\n### Usage Examples\n\nThere are three formats you can use to run this task.\n\n#### Short\n\n```js\nclean: [\"path/to/dir/one\", \"path/to/dir/two\"]\n```\n\n#### Medium (specific targets with global options)\n\n```js\nclean: {\n build: [\"path/to/dir/one\", \"path/to/dir/two\"],\n release: [\"path/to/another/dir/one\", \"path/to/another/dir/two\"]\n},\n```\n\n#### Long (specific targets with per target options)\n\n```js\nclean: {\n build: {\n src: [\"path/to/dir/one\", \"path/to/dir/two\"]\n }\n}\n```\n\n## Release History\n\n * 2013-07-15   v0.5.0   Use rimraf directly, version 2.2.1 to fix issue on Windows. Add no-write option to mimic grunt.file.delete behavior.\n * 2013-04-16   v0.4.1   Check if file exists to avoid trying to delete a non-existent file.\n * 2013-02-15   v0.4.0   First official release for Grunt 0.4.0.\n * 2013-01-18   v0.4.0rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.\n * 2013-01-09   v0.4.0rc5   Updating to work with grunt v0.4.0rc5. Switching to this.filesSrc api.\n * 2012-12-07   v0.4.0a   Conversion to grunt v0.4 conventions. Remove node v0.6 and grunt v0.3 support. Add force option to bypass CWD check.\n * 2012-09-23   v0.3.0   Options no longer accepted from global config key.\n * 2012-09-10   v0.2.0   Refactored from grunt-contrib into individual repo.\n\n---\n\nTask submitted by [Tim Branyen](http://tbranyen.com/)\n\n*This file was generated on Mon Jul 15 2013 20:45:46.*\n", + "readmeFilename": "README.md", + "_id": "grunt-contrib-clean@0.5.0", + "dist": { + "shasum": "631a9019483ca0235a8213f712c9783c74bd9d9a" + }, + "_from": "grunt-contrib-clean@~0.5.0", + "_resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz" +} diff --git a/node_modules/grunt-contrib-clean/tasks/clean.js b/node_modules/grunt-contrib-clean/tasks/clean.js new file mode 100644 index 000000000..0f225c5f2 --- /dev/null +++ b/node_modules/grunt-contrib-clean/tasks/clean.js @@ -0,0 +1,62 @@ +/* + * grunt-contrib-clean + * http://gruntjs.com/ + * + * Copyright (c) 2013 Tim Branyen, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +var rimraf = require('rimraf'); + +module.exports = function(grunt) { + + function clean(filepath, options) { + if (!grunt.file.exists(filepath)) { + return false; + } + + grunt.log.write((options['no-write'] ? 'Not actually cleaning ' : 'Cleaning ') + filepath + '...'); + + // Only delete cwd or outside cwd if --force enabled. Be careful, people! + if (!options.force) { + if (grunt.file.isPathCwd(filepath)) { + grunt.verbose.error(); + grunt.fail.warn('Cannot delete the current working directory.'); + return false; + } else if (!grunt.file.isPathInCwd(filepath)) { + grunt.verbose.error(); + grunt.fail.warn('Cannot delete files outside the current working directory.'); + return false; + } + } + + try { + // Actually delete. Or not. + if (!options['no-write']) { + rimraf.sync(filepath); + } + grunt.log.ok(); + } catch (e) { + grunt.log.error(); + grunt.fail.warn('Unable to delete "' + filepath + '" file (' + e.message + ').', e); + } + } + + grunt.registerMultiTask('clean', 'Clean files and folders.', function() { + // Merge task-specific and/or target-specific options with these defaults. + var options = this.options({ + force: grunt.option('force') === true, + 'no-write': grunt.option('no-write') === true, + }); + + grunt.verbose.writeflags(options, 'Options'); + + // Clean specified files / dirs. + this.filesSrc.forEach(function(filepath) { + clean(filepath, options); + }); + }); + +}; diff --git a/node_modules/grunt-contrib-clean/test/clean_test.js b/node_modules/grunt-contrib-clean/test/clean_test.js new file mode 100644 index 000000000..4db2ef822 --- /dev/null +++ b/node_modules/grunt-contrib-clean/test/clean_test.js @@ -0,0 +1,22 @@ +'use strict'; + +var grunt = require('grunt'); + +exports.clean = { + short: function(test) { + test.expect(1); + + var expected = grunt.file.exists('tmp/sample_short'); + test.equal(expected, false, 'should remove the short directory using clean'); + + test.done(); + }, + long: function(test) { + test.expect(1); + + var expected = grunt.file.exists('tmp/sample_long'); + test.equal(expected, false, 'should remove the long directory using clean'); + + test.done(); + } +}; diff --git a/node_modules/grunt-contrib-clean/test/fixtures/sample_long/long.txt b/node_modules/grunt-contrib-clean/test/fixtures/sample_long/long.txt new file mode 100644 index 000000000..83f9fcffd --- /dev/null +++ b/node_modules/grunt-contrib-clean/test/fixtures/sample_long/long.txt @@ -0,0 +1 @@ +txt diff --git a/node_modules/grunt-contrib-clean/test/fixtures/sample_short/short.txt b/node_modules/grunt-contrib-clean/test/fixtures/sample_short/short.txt new file mode 100644 index 000000000..83f9fcffd --- /dev/null +++ b/node_modules/grunt-contrib-clean/test/fixtures/sample_short/short.txt @@ -0,0 +1 @@ +txt diff --git a/node_modules/grunt-contrib-jshint/.jshintignore b/node_modules/grunt-contrib-jshint/.jshintignore new file mode 100644 index 000000000..7365357ae --- /dev/null +++ b/node_modules/grunt-contrib-jshint/.jshintignore @@ -0,0 +1 @@ +test/fixtures/dontlint.txt \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/.jshintrc b/node_modules/grunt-contrib-jshint/.jshintrc new file mode 100644 index 000000000..6b6188142 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/.jshintrc @@ -0,0 +1,13 @@ +{ + "curly": true, // true: Require {} for every new block or scope + "eqeqeq": true, // true: Require triple equals (===) for comparison + "immed": true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` + "latedef": true, // true: Require variables/functions to be defined before being used + "newcap": true, // true: Require capitalization of all constructor functions e.g. `new F()` + "noarg": true, // true: Prohibit use of `arguments.caller` and `arguments.callee` + "sub": true, // true: Tolerate using `[]` notation when it can still be expressed in dot notation + "undef": true, // true: Require all non-global variables to be declared (prevents global leaks) + "boss": true, // true: Tolerate assignments where comparisons would be expected + "eqnull": true, // true: Tolerate use of `== null` + "node": true // Node.js +} diff --git a/node_modules/grunt-contrib-jshint/.npmignore b/node_modules/grunt-contrib-jshint/.npmignore new file mode 100644 index 000000000..5cb6bfd4d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/.travis.yml b/node_modules/grunt-contrib-jshint/.travis.yml new file mode 100644 index 000000000..57661910e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/AUTHORS b/node_modules/grunt-contrib-jshint/AUTHORS new file mode 100644 index 000000000..75165ef8c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/AUTHORS @@ -0,0 +1,2 @@ +"Cowboy" Ben Alman (http://benalman.com/) +Tyler Kellen (http://goingslowly.com/) diff --git a/node_modules/grunt-contrib-jshint/CHANGELOG b/node_modules/grunt-contrib-jshint/CHANGELOG new file mode 100644 index 000000000..d44f837f5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/CHANGELOG @@ -0,0 +1,93 @@ +v0.6.5: + date: 2013-10-23 + changes: + - Fix output when maxerr is low. +v0.6.4: + date: 2013-08-29 + changes: + - jshintrc now loaded by jshint allowing comments. +v0.6.3: + date: 2013-08-15 + changes: + - Fix module location for jshint 2.1.10. +v0.6.2: + date: 2013-07-29 + changes: + - Update to jshint 2.1.7. +v0.6.1: + date: 2013-07-27 + changes: + - Peg jshint to 2.1.4 until breaking changes in 2.1.5 are fixed. +v0.6.0: + date: 2013-06-02 + changes: + - Dont always succeed the task when using a custom reporter. + - Bump jshint to 2.1.3. +v0.5.4: + date: 2013-05-22 + changes: + - Fix default reporter to show offending file. +v0.5.3: + date: 2013-05-19 + changes: + - "Performance: Execute the reporter once rather than per file." +v0.5.2: + date: 2013-05-18 + changes: + - Fix printing too many erroneous ignored file errors. +v0.5.1: + date: 2013-05-17 + changes: + - Fix for when only 1 file is lint free. +v0.5.0: + date: 2013-05-17 + changes: + - Bump to jshint 2.0. + - Add support for .jshintignore files and ignores option + - Add support for extensions option. + - Add support for custom reporters and output report to a file. +v0.4.3: + date: 2013-04-08 + changes: + - Fix evaluation of predef option when it's an object. +v0.4.2: + date: 2013-04-08 + changes: + - Avoid wiping force option when jshintrc is used. +v0.4.1: + date: 2013-04-06 + changes: + - Fix to allow object type for deprecated predef. +v0.4.0: + date: 2013-04-04 + changes: + - Revert task level options to override jshintrc files. +v0.3.0: + date: 2013-03-13 + changes: + - Bump to JSHint 1.1.0. + - Add force option to report JSHint errors but not fail the task. + - Add error/warning code to message. + - Allow task level options to override jshintrc file. +v0.2.0: + date: 2013-02-26 + changes: + - Bump to JSHint 1.0 +v0.1.1: + date: 2013-02-15 + changes: + - First official release for Grunt 0.4.0. +v0.1.1rc6: + date: 2013-01-18 + changes: + - Updating grunt/gruntplugin dependencies to rc6. + - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. +v0.1.1rc5: + date: 2013-01-09 + changes: + - Updating to work with grunt v0.4.0rc5. + - Switching to this.filesSrc api. +v0.1.0: + date: 2012-10-18 + changes: + - Work in progress, not yet officially released. diff --git a/node_modules/grunt-contrib-jshint/CONTRIBUTING.md b/node_modules/grunt-contrib-jshint/CONTRIBUTING.md new file mode 100644 index 000000000..5d08cc387 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/CONTRIBUTING.md @@ -0,0 +1 @@ +Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project. diff --git a/node_modules/grunt-contrib-jshint/Gruntfile.js b/node_modules/grunt-contrib-jshint/Gruntfile.js new file mode 100644 index 000000000..0a65eeba8 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/Gruntfile.js @@ -0,0 +1,63 @@ +/* + * grunt-contrib-jshint + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + jshint: { + allFiles: [ + 'Gruntfile.js', + 'tasks/**/*.js', + '<%= nodeunit.tests %>', + ], + individualFiles: { + files: [ + {src: 'Gruntfile.js'}, + {src: 'tasks/**/*.js'}, + {src: '<%= nodeunit.tests %>'}, + ], + }, + withReporterShouldFail: { + options: { + reporter: 'checkstyle', + reporterOutput: 'tmp/report.xml', + force: true, + }, + src: ['test/fixtures/missingsemicolon.js'], + }, + ignoresSupport: { + src: ['test/fixtures/dontlint.txt'], + }, + options: { + jshintrc: '.jshintrc', + }, + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'], + }, + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-internal'); + + // Whenever the "test" task is run, run the "nodeunit" task. + grunt.registerTask('test', ['jshint', 'nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['test', 'build-contrib']); + +}; diff --git a/node_modules/grunt-contrib-jshint/LICENSE-MIT b/node_modules/grunt-contrib-jshint/LICENSE-MIT new file mode 100644 index 000000000..836884976 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2013 "Cowboy" Ben Alman, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-jshint/README.md b/node_modules/grunt-contrib-jshint/README.md new file mode 100644 index 000000000..2aad1790a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/README.md @@ -0,0 +1,232 @@ +# grunt-contrib-jshint v0.6.5 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-jshint.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-jshint) + +> Validate files with JSHint. + + + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-contrib-jshint --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-contrib-jshint'); +``` + + + + +## Jshint task +_Run this task with the `grunt jshint` command._ + +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. + +For more explanations of the lint errors JSHint will throw at you please visit [jslinterrors.com](http://jslinterrors.com/). + +### Options + +Any specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options. + +[JSHint]: http://www.jshint.com/ +[JSHint documentation]: http://www.jshint.com/docs/ + +A few additional options are supported: + +#### globals +Type: `Object` +Default value: `null` + +A map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the `JSHINT` function as its third argument. See the [JSHint documentation][] for more information. + +#### jshintrc +Type: `String` +Default value: `null` + +If this filename is specified, options and globals defined therein will be used. The `jshintrc` file must be valid JSON and looks something like this: + +```json +{ + "curly": true, + "eqnull": true, + "eqeqeq": true, + "undef": true, + "globals": { + "jQuery": true + } +} +``` + +*Be aware that `jshintrc` settings are not merged with your Grunt options.* + +#### extensions +Type: `String` +Default value: `''` + +A list of non-dot-js extensions to check. + +#### ignores +Type: `Array` +Default value: `null` + +A list of files and dirs to ignore. This will override your `.jshintignore` file if set and does not merge. + +#### force +Type: `Boolean` +Default value: `false` + +Set `force` to `true` to report JSHint errors but not fail the task. + +#### reporter +Type: `String` +Default value: `null` + +Allows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: `jslint` or `checkstyle`. + +See also: [Writing your own JSHint reporter.](http://jshint.com/docs/reporters/) + +#### reporterOutput +Type: `String` +Default value: `null` + +Specify a filepath to output the results of a reporter. If `reporterOutput` is specified then all output will be written to the given filepath instead of printed to stdout. + +### Usage examples + +#### Wildcards +In this example, running `grunt jshint:all` (or `grunt jshint` because `jshint` is a [multi task](http://gruntjs.com/configuring-tasks#task-configuration-and-targets)) will lint the project's Gruntfile as well as all JavaScript files in the `lib` and `test` directories and their subdirectores, using the default JSHint options. + +```js +// Project configuration. +grunt.initConfig({ + jshint: { + all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] + } +}); +``` + +#### Linting before and after concatenating +In this example, running `grunt jshint` will lint both the "beforeconcat" set and "afterconcat" sets of files. This is not ideal, because `dist/output.js` may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) `concat` task. + +In this case, you should lint the "beforeconcat" files first, then concat, then lint the "afterconcat" files, by running `grunt jshint:beforeconcat concat jshint:afterconcat`. + +```js +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/foo.js', 'src/bar.js'], + dest: 'dist/output.js' + } + }, + jshint: { + beforeconcat: ['src/foo.js', 'src/bar.js'], + afterconcat: ['dist/output.js'] + } +}); +``` + +#### Specifying JSHint options and globals + +In this example, custom JSHint options are specified. Note that when `grunt jshint:uses_defaults` is run, those files are linted using the default options, but when `grunt jshint:with_overrides` is run, those files are linted using _merged_ task/target options. + +```js +// Project configuration. +grunt.initConfig({ + jshint: { + options: { + curly: true, + eqeqeq: true, + eqnull: true, + browser: true, + globals: { + jQuery: true + }, + }, + uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'], + with_overrides: { + options: { + curly: false, + undef: true, + }, + files: { + src: ['dir3/**/*.js', 'dir4/**/*.js'] + }, + } + }, +}); +``` + +#### Ignoring specific warnings + +If you would like to ignore a specific warning: + +```shell +[L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9. +``` + +You can toggle it by prepending `-` to the warning id as an option: + +```js +grunt.initConfig({ + jshint: { + ignore_warning: { + options: { + '-W015': true, + }, + src: ['**/*.js'], + }, + }, +}); +``` + +#### Ignoring specific files + +Occasionally application files and third party libraries share the same directory. To exclude third party code, but include all current and future application files, use a glob for `files` and specifically exclude libraries using `ignores`. In this example, the jQuery file is matched by the glob but subsequently ignored when JSHint does its analysis. + +```js +grunt.initConfig({ + jshint: { + files: ['js/*.js'], + options: { + ignores: ['js/jquery.js'] + } + } +}); +``` + + +## Release History + + * 2013-10-23   v0.6.5   Fix output when maxerr is low. + * 2013-08-29   v0.6.4   jshintrc now loaded by jshint allowing comments. + * 2013-08-15   v0.6.3   Fix module location for jshint 2.1.10. + * 2013-07-29   v0.6.2   Update to jshint 2.1.7. + * 2013-07-27   v0.6.1   Peg jshint to 2.1.4 until breaking changes in 2.1.5 are fixed. + * 2013-06-02   v0.6.0   Dont always succeed the task when using a custom reporter. Bump jshint to 2.1.3. + * 2013-05-22   v0.5.4   Fix default reporter to show offending file. + * 2013-05-19   v0.5.3   Performance: Execute the reporter once rather than per file. + * 2013-05-18   v0.5.2   Fix printing too many erroneous ignored file errors. + * 2013-05-17   v0.5.1   Fix for when only 1 file is lint free. + * 2013-05-17   v0.5.0   Bump to jshint 2.0. Add support for .jshintignore files and ignores option Add support for extensions option. Add support for custom reporters and output report to a file. + * 2013-04-08   v0.4.3   Fix evaluation of predef option when it's an object. + * 2013-04-08   v0.4.2   Avoid wiping force option when jshintrc is used. + * 2013-04-06   v0.4.1   Fix to allow object type for deprecated predef. + * 2013-04-04   v0.4.0   Revert task level options to override jshintrc files. + * 2013-03-13   v0.3.0   Bump to JSHint 1.1.0. Add force option to report JSHint errors but not fail the task. Add error/warning code to message. Allow task level options to override jshintrc file. + * 2013-02-26   v0.2.0   Bump to JSHint 1.0 + * 2013-02-15   v0.1.1   First official release for Grunt 0.4.0. + * 2013-01-18   v0.1.1rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. + * 2013-01-09   v0.1.1rc5   Updating to work with grunt v0.4.0rc5. Switching to this.filesSrc api. + * 2012-10-18   v0.1.0   Work in progress, not yet officially released. + +--- + +Task submitted by ["Cowboy" Ben Alman](http://benalman.com/) + +*This file was generated on Wed Oct 23 2013 20:33:11.* diff --git a/node_modules/grunt-contrib-jshint/docs/jshint-examples.md b/node_modules/grunt-contrib-jshint/docs/jshint-examples.md new file mode 100644 index 000000000..a64ef6519 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/docs/jshint-examples.md @@ -0,0 +1,103 @@ +# Usage examples + +## Wildcards +In this example, running `grunt jshint:all` (or `grunt jshint` because `jshint` is a [multi task](http://gruntjs.com/configuring-tasks#task-configuration-and-targets)) will lint the project's Gruntfile as well as all JavaScript files in the `lib` and `test` directories and their subdirectores, using the default JSHint options. + +```js +// Project configuration. +grunt.initConfig({ + jshint: { + all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] + } +}); +``` + +## Linting before and after concatenating +In this example, running `grunt jshint` will lint both the "beforeconcat" set and "afterconcat" sets of files. This is not ideal, because `dist/output.js` may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) `concat` task. + +In this case, you should lint the "beforeconcat" files first, then concat, then lint the "afterconcat" files, by running `grunt jshint:beforeconcat concat jshint:afterconcat`. + +```js +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/foo.js', 'src/bar.js'], + dest: 'dist/output.js' + } + }, + jshint: { + beforeconcat: ['src/foo.js', 'src/bar.js'], + afterconcat: ['dist/output.js'] + } +}); +``` + +## Specifying JSHint options and globals + +In this example, custom JSHint options are specified. Note that when `grunt jshint:uses_defaults` is run, those files are linted using the default options, but when `grunt jshint:with_overrides` is run, those files are linted using _merged_ task/target options. + +```js +// Project configuration. +grunt.initConfig({ + jshint: { + options: { + curly: true, + eqeqeq: true, + eqnull: true, + browser: true, + globals: { + jQuery: true + }, + }, + uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'], + with_overrides: { + options: { + curly: false, + undef: true, + }, + files: { + src: ['dir3/**/*.js', 'dir4/**/*.js'] + }, + } + }, +}); +``` + +## Ignoring specific warnings + +If you would like to ignore a specific warning: + +```shell +[L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9. +``` + +You can toggle it by prepending `-` to the warning id as an option: + +```js +grunt.initConfig({ + jshint: { + ignore_warning: { + options: { + '-W015': true, + }, + src: ['**/*.js'], + }, + }, +}); +``` + +## Ignoring specific files + +Occasionally application files and third party libraries share the same directory. To exclude third party code, but include all current and future application files, use a glob for `files` and specifically exclude libraries using `ignores`. In this example, the jQuery file is matched by the glob but subsequently ignored when JSHint does its analysis. + +```js +grunt.initConfig({ + jshint: { + files: ['js/*.js'], + options: { + ignores: ['js/jquery.js'] + } + } +}); +``` diff --git a/node_modules/grunt-contrib-jshint/docs/jshint-options.md b/node_modules/grunt-contrib-jshint/docs/jshint-options.md new file mode 100644 index 000000000..d1369a046 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/docs/jshint-options.md @@ -0,0 +1,66 @@ +# Options + +Any specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options. + +[JSHint]: http://www.jshint.com/ +[JSHint documentation]: http://www.jshint.com/docs/ + +A few additional options are supported: + +## globals +Type: `Object` +Default value: `null` + +A map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the `JSHINT` function as its third argument. See the [JSHint documentation][] for more information. + +## jshintrc +Type: `String` +Default value: `null` + +If this filename is specified, options and globals defined therein will be used. The `jshintrc` file must be valid JSON and looks something like this: + +```json +{ + "curly": true, + "eqnull": true, + "eqeqeq": true, + "undef": true, + "globals": { + "jQuery": true + } +} +``` + +*Be aware that `jshintrc` settings are not merged with your Grunt options.* + +## extensions +Type: `String` +Default value: `''` + +A list of non-dot-js extensions to check. + +## ignores +Type: `Array` +Default value: `null` + +A list of files and dirs to ignore. This will override your `.jshintignore` file if set and does not merge. + +## force +Type: `Boolean` +Default value: `false` + +Set `force` to `true` to report JSHint errors but not fail the task. + +## reporter +Type: `String` +Default value: `null` + +Allows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: `jslint` or `checkstyle`. + +See also: [Writing your own JSHint reporter.](http://jshint.com/docs/reporters/) + +## reporterOutput +Type: `String` +Default value: `null` + +Specify a filepath to output the results of a reporter. If `reporterOutput` is specified then all output will be written to the given filepath instead of printed to stdout. diff --git a/node_modules/grunt-contrib-jshint/docs/jshint-overview.md b/node_modules/grunt-contrib-jshint/docs/jshint-overview.md new file mode 100644 index 000000000..70cb954ca --- /dev/null +++ b/node_modules/grunt-contrib-jshint/docs/jshint-overview.md @@ -0,0 +1,3 @@ +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. + +For more explanations of the lint errors JSHint will throw at you please visit [jslinterrors.com](http://jslinterrors.com/). diff --git a/node_modules/grunt-contrib-jshint/node_modules/.bin/jshint b/node_modules/grunt-contrib-jshint/node_modules/.bin/jshint new file mode 120000 index 000000000..1b5b30ca1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/.bin/jshint @@ -0,0 +1 @@ +../jshint/bin/jshint \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/README.md new file mode 100644 index 000000000..c37da2536 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/README.md @@ -0,0 +1,40 @@ +JSHint, A Static Code Analysis Tool for JavaScript +-------------------------------------------------- + +\[ [Use it online](http://jshint.com/) • [About](http://jshint.com/about/) • +[Docs](http://jshint.com/docs/) • [FAQ](http://jshint.com/docs/faq) • +[Install](http://jshint.com/install/) • [Hack](http://jshint.com/hack/) • +[Blog](http://jshint.com/blog/) • [Twitter](https://twitter.com/jshint/) \] + +[![Build Status](https://travis-ci.org/jshint/jshint.png?branch=master)](https://travis-ci.org/jshint/jshint) +[![NPM version](https://badge.fury.io/js/jshint.png)](http://badge.fury.io/js/jshint) + +JSHint is a community-driven tool to detect errors and potential problems +in JavaScript code and to enforce your team’s coding conventions. It is +very flexible so you can easily adjust it to your particular coding guidelines +and the environment you expect your code to execute in. + +#### Reporting a bug + +To report a bug simply create a +[new GitHub Issue](https://github.com/jshint/jshint/issues/new) and describe +your problem or suggestion. We welcome all kind of feedback regarding +JSHint including but not limited to: + + * When JSHint doesn't work as expected + * When JSHint complains about valid JavaScript code that works in all browsers + * When you simply want a new option or feature + +Before reporting a bug look around to see if there are any open or closed tickets +that cover your issue. And remember the wisdom: pull request > bug report > tweet. + + +#### License + +JSHint is distributed under the MIT License. One file and one file only +(src/stable/jshint.js) is distributed under the slightly modified MIT License. + + +#### Thank you! + +We really appreciate all kind of feedback and contributions. Thanks for using and supporting JSHint! diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/apply b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/apply new file mode 100755 index 000000000..ab0da4086 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/apply @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +var shjs = require("shelljs"); +var url = "https://github.com/jshint/jshint/pull/" + process.argv[2] + ".diff"; + +shjs.exec('curl "' + url + '" | git apply'); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/build b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/build new file mode 100755 index 000000000..92dd2f9a4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/build @@ -0,0 +1,32 @@ +#!/usr/bin/env node +/*jshint shelljs:true */ + +"use strict"; + +var browserify = require("browserify"); +var bundle = browserify("./src/jshint.js"); +var version = require("../package.json").version; +require("shelljs/make"); + +if (!test("-e", "../dist")) + mkdir("../dist"); + +bundle.require("./src/jshint.js", { expose: "jshint" }); +bundle.bundle({}, function (err, src) { + var web = "./dist/jshint-" + version + ".js"; + var rhino = "./dist/jshint-rhino-" + version + ".js"; + + [ "// " + version, + "var JSHINT;", + "var window;", + "if (typeof window === 'undefined') window = {};", + "(function () {", + "var require;", + src, + "JSHINT = require('jshint').JSHINT;", + "}());" + ].join("\n").to(web); + + ("#!/usr/bin/env rhino\nvar window = {};\n" + cat(web, "./src/platforms/rhino.js")).to(rhino); + chmod("+x", rhino); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/changelog b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/changelog new file mode 100755 index 000000000..48f5e6f4c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/changelog @@ -0,0 +1,36 @@ +#!/usr/bin/env node +/*jshint shelljs:true, lastsemic:true, -W101*/ + +"use strict"; + +var version = require("../package.json").version; +require("shelljs/make"); + +exec("git log --format='%H|%h|%an|%s' " + version + "..HEAD", { silent: true }, function (code, output) { + if (code !== 0) + return void console.log("git log return code is non-zero"); + + var commits = output.split("\n") + .filter(function (cmt) { return cmt.trim() !== "" }) + .map(function (cmt) { return cmt.split("|") }); + + var html = ""; + var authors = {}; + + commits.forEach(function (cmt) { + var tr = ""; + tr += "" + cmt[1] + ""; + tr += "" + cmt[3].replace(/(#(\d+))/, "$1") + ""; + html += "" + tr + "\n"; + + if (cmt[2] !== "Anton Kovalyov") + authors[cmt[2]] = true; + }); + + echo(""); + echo("\n" + html + "
\n"); + + if (Object.keys(authors).length) { + echo("

Thanks to " + Object.keys(authors).join(", ") + " for sending patches!

"); + } +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/jshint b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/jshint new file mode 100755 index 000000000..f56105fd8 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/jshint @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +require("../src/cli.js").interpret(process.argv); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/land b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/land new file mode 100755 index 000000000..2e3c026be --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/bin/land @@ -0,0 +1,37 @@ +#!/usr/bin/env node + +var url = "https://github.com/jshint/jshint/pull/" + process.argv[2] + ".patch"; +var https = require("https"); +var shjs = require("shelljs"); +var opts = require("url").parse(url); +var msg = process.argv[3]; + +opts.rejectUnauthorized = false; +opts.agent = new https.Agent(opts); + +https.get(opts, succ).on("error", err); + +function succ(res) { + if (res.statusCode !== 200) + return void console.log("error:", res.statusCode); + + var data = ""; + res.on("data", function (chunk) { + data += chunk.toString(); + }); + + res.on("end", function () { + data = data.split("\n"); + data = data[1].replace(/^From\:\s/, ""); + data = data.replace(/"/g, ""); + + shjs.exec("git commit -s --author=\"" + data + "\" --message=\"" + msg + "\""); + }) +} + +function err(res) { + console.log("error:", res.message); +} + + + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/.bin/shjs b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/.bin/shjs new file mode 120000 index 000000000..a0449975b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/.bin/shjs @@ -0,0 +1 @@ +../shelljs/bin/shjs \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/README.md new file mode 100644 index 000000000..0fe30d4fb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/README.md @@ -0,0 +1,196 @@ +**cli is a toolkit for rapidly building command line apps - it includes:** + +- Full featured opts/args parser +- Plugin support for adding common options and switches +- Helper methods for working with input/output and spawning child processes +- Output colored/styled messages, [progress bars](https://github.com/chriso/cli/blob/master/examples/progress.js) or [spinners](https://github.com/chriso/cli/blob/master/examples/spinner.js) +- Command [auto-completion](https://github.com/chriso/cli/blob/master/examples/command.js) and [glob support](https://github.com/chriso/cli/blob/master/examples/glob.js) + +Install using `npm install cli` or just bundle [cli.js](https://github.com/chriso/cli/raw/master/cli-min.js) with your app. + +## Example apps + +### sort.js + +```javascript +#!/usr/bin/env node +require('cli').withStdinLines(function(lines, newline) { + this.output(lines.sort().join(newline)); +}); +``` + +Try it out + +```bash +$ ./sort.js < input.txt +``` + +Let's add support for an `-n` switch to use a numeric sort, and a `-r` switch to reverse output - only 5 extra lines of code (!) + +```javascript +var cli = require('cli'), options = cli.parse(); + +cli.withStdinLines(function(lines, newline) { + lines.sort(!options.n ? null : function(a, b) { + return parseInt(a) > parseInt(b); + }); + if (options.r) lines.reverse(); + this.output(lines.join(newline)); +}); +``` + +### static.js + +Let's create a static file server with daemon support to see the opts parser + plugins in use - note: this requires `npm install creationix daemon` + +```javascript +var cli = require('cli').enable('daemon', 'status'); //Enable 2 plugins + +cli.parse({ + log: ['l', 'Enable logging'], + port: ['p', 'Listen on this port', 'number', 8080], + serve: [false, 'Serve static files from PATH', 'path', './public'] +}); + +cli.main(function(args, options) { + var server, middleware = []; + + if (options.log) { + this.debug('Enabling logging'); + middleware.push(require('creationix/log')()); + } + + this.debug('Serving files from ' + options.serve); + middleware.push(require('creationix/static')('/', options.serve, 'index.html')); + + server = this.createServer(middleware).listen(options.port); + + this.ok('Listening on port ' + options.port); +}); +``` + +To output usage information + +```bash +$ ./static.js --help +``` + +To create a daemon that serves files from */tmp*, run + +```bash +$ ./static.js -ld --serve=/tmp +``` + +For more examples, see [./examples](https://github.com/chriso/cli/tree/master/examples) + +## Helper methods + +cli has methods that collect stdin (newline is autodetected as \n or \r\n) + +```javascript +cli.withStdin(callback); //callback receives stdin as a string +cli.withStdinLines(callback); //callback receives stdin split into an array of lines (lines, newline) +``` + +cli also has a lower level method for working with input line by line (see [./examples/cat.js](https://github.com/chriso/cli/blob/master/examples/cat.js) for an example). + +```javascript +cli.withInput(file, function (line, newline, eof) { + if (!eof) { + this.output(line + newline); + } +}); +``` + +*Note: `file` can be omitted if you want to work with stdin* + +To output a progress bar, call + +```javascript +cli.progress(progress); //Where 0 <= progress <= 1 +``` + +To spawn a child process, use + +```javascript +cli.exec(cmd, callback); //callback receives the output of the process (split into lines) +``` + +cli also comes bundled with kof's [node-natives](https://github.com/kof/node-natives) (access with cli.native) and creationix' [stack](https://github.com/creationix/stack) (access with cli.createServer) + +## Plugins + +Plugins are a way of adding common opts and can be enabled using + +```javascript +cli.enable(plugin1, [plugin2, ...]); //To disable, use the equivalent disable() method +``` + +**help** - *enabled by default* + +Adds `-h,--help` to output auto-generated usage information + +**version** + +Adds `-v,--version` to output version information for the app. cli will attempt to locate and parse a nearby *package.json* + +To set your own app name and version, use `cli.setApp(app_name, version)` + +**status** + +Adds options to show/hide the stylized status messages that are output to the console when using one of these methods + +```javascript +cli.debug(msg); //Only shown when using --debug +cli.error(msg); +cli.fatal(msg); //Exits the process after outputting msg +cli.info(msg); +cli.ok(msg); +``` + +`-k,--no-color` will omit ANSI color escapes from the output + +**glob** - *requires* `npm install glob` + +Enables glob matching of arguments + +**daemon** - *requires* `npm install daemon` + +Adds `-d,--daemon ARG` for daemonizing the process and controlling the resulting daemon + +`ARG` can be either start (default), stop, restart, pid (outputs the daemon's pid if it's running), or log (output the daemon's stdout+stderr) + +**timeout** + +Adds `-t,--timeout N` to exit the process after N seconds with an error + +**catchall** + +Adds `-c,--catch` to catch and output uncaughtExceptions and resume execution + +*Note: Plugins are automatically disabled if an option or switch of the same name is already defined* + +## LICENSE + +(MIT license) + +Copyright (c) 2010 Chris O'Hara + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/cli.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/cli.js new file mode 100644 index 000000000..f94e973f2 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/cli.js @@ -0,0 +1,1133 @@ +/** + * Copyright (c) 2010 Chris O'Hara + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + //Note: cli includes kof/node-natives and creationix/stack. I couldn't find + //license information for either - contact me if you want your license added + +var cli = exports, + argv, curr_opt, curr_val, full_opt, is_long, + short_tags = [], opt_list, parsed = {}, + usage, argv_parsed, command_list, commands, + daemon, daemon_arg, no_color, show_debug; + +cli.app = null; +cli.version = null; +cli.argv = []; +cli.argc = 0; + +cli.options = {}; +cli.args = []; +cli.command; + +cli.width = 70; +cli.option_width = 25; + +/** + * Bind kof's node-natives (https://github.com/kof/node-natives) to `cli.native` + * + * Rather than requiring node natives (e.g. var fs = require('fs')), all + * native modules can be accessed like `cli.native.fs` + */ +cli.native = {}; +var define_native = function (module) { + Object.defineProperty(cli.native, module, { + enumerable: true, + configurable: true, + get: function() { + delete cli.native[module]; + return cli.native[module] = require(module); + } + }); +}; +var natives = process.binding('natives'); +for (var module in natives) { + define_native(module); +} + +cli.output = cli.native.util.print; +cli.exit = process.exit; + +/** + * Define plugins. Plugins can be enabled and disabled by calling: + * + * `cli.enable(plugin1, [plugin2, ...])` + * `cli.disable(plugin1, [plugin2, ...])` + * + * Methods are chainable - `cli.enable(plugin).disable(plugin2)`. + * + * The 'help' plugin is enabled by default. + */ +var enable = { + help: true, //Adds -h, --help + version: false, //Adds -v,--version => gets version by parsing a nearby package.json + daemon: false, //Adds -d,--daemon [ARG] => (see cli.daemon() below) + status: false, //Adds -k,--no-color & --debug => display plain status messages /display debug messages + timeout: false, //Adds -t,--timeout N => timeout the process after N seconds + catchall: false, //Adds -c,--catch => catch and output uncaughtExceptions + glob: false //Adds glob matching => use cli.glob(arg) +} +cli.enable = function (/*plugins*/) { + Array.prototype.slice.call(arguments).forEach(function (plugin) { + switch (plugin) { + case 'daemon': + try { + daemon = require('daemon'); + if (typeof daemon.daemonize !== 'function') { + throw 'Invalid module'; + } + } catch (e) { + cli.fatal('daemon.node not installed. Please run `npm install daemon`'); + } + break; + case 'catchall': + process.on('uncaughtException', function (err) { + cli.error('Uncaught exception: ' + (err.msg || err)); + }); + break; + case 'help': case 'version': case 'status': + case 'autocomplete': case 'timeout': + //Just add switches. + break; + case 'glob': + cli.glob = require('glob'); + break; + default: + cli.fatal('Unknown plugin "' + plugin + '"'); + break; + } + enable[plugin] = true; + }); + return cli; +} +cli.disable = function (/*plugins*/) { + Array.prototype.slice.call(arguments).forEach(function (plugin) { + if (enable[plugin]) { + enable[plugin] = false; + } + }); + return cli; +} + +/** + * Sets argv (default is process.argv). + * + * @param {Array|String} argv + * @param {Boolean} keep_arg0 (optional - default is false) + * @api public + */ +cli.setArgv = function (arr, keep_arg0) { + if (typeof arr == 'string') { + arr = arr.split(' '); + } else { + arr = arr.slice(); + } + cli.app = arr.shift(); + //Strip off argv[0] if it's a node binary + if (!keep_arg0 && ('node' === cli.native.path.basename(cli.app) + || process.execPath === cli.app)) { + cli.app = arr.shift(); + } + cli.app = cli.native.path.basename(cli.app); + argv_parsed = false; + cli.args = cli.argv = argv = arr; + cli.argc = argv.length; + cli.options = {}; + cli.command = null; +}; +cli.setArgv(process.argv); + +/** + * Returns the next opt, or false if no opts are found. + * + * @return {String} opt + * @api public + */ +cli.next = function () { + if (!argv_parsed) { + cli.args = []; + argv_parsed = true; + } + + curr_val = null; + + //If we're currently in a group of short opts (e.g. -abc), return the next opt + if (short_tags.length) { + curr_opt = short_tags.shift(); + full_opt = '-' + curr_opt; + return curr_opt; + } + + if (!argv.length) { + return false; + } + + curr_opt = argv.shift(); + + //If an escape sequence is found (- or --), subsequent opts are ignored + if (curr_opt === '-' || curr_opt === '--') { + while (argv.length) { + cli.args.push(argv.shift()); + } + return false; + } + + //If the next element in argv isn't an opt, add it to the list of args + if (curr_opt[0] !== '-') { + cli.args.push(curr_opt); + return cli.next(); + } else { + //Check if the opt is short/long + is_long = curr_opt[1] === '-'; + curr_opt = curr_opt.substr(is_long ? 2 : 1); + } + + //Accept grouped short opts, e.g. -abc => -a -b -c + if (!is_long && curr_opt.length > 1) { + short_tags = curr_opt.split(''); + return cli.next(); + } + + var eq, len; + + //Check if the long opt is in the form --option=VALUE + if (is_long && (eq = curr_opt.indexOf('=')) >= 0) { + curr_val = curr_opt.substr(eq + 1); + curr_opt = curr_opt.substr(0, eq); + len = curr_val.length; + //Allow values to be quoted + if ((curr_val[0] === '"' && curr_val[len - 1] === '"') || + (curr_val[0] === "'" && curr_val[len - 1] === "'")) + { + curr_val = curr_val.substr(1, len-2); + } + if (curr_val.match(/^[0-9]+$/)) { + curr_val = parseInt(curr_val, 10); + } + } + + //Save the opt representation for later + full_opt = (is_long ? '--' : '-') + curr_opt; + + return curr_opt; +}; + +/** + * Parses command line opts. + * + * `opts` must be an object with opts defined like: + * long_tag: [short_tag, description, value_type, default_value]; + * + * `commands` is an optional array or object for apps that are of the form + * my_app [OPTIONS] [ARGS] + * The command list is output with usage information + there is bundled + * support for auto-completion, etc. + * + * See README.md for more information. + * + * @param {Object} opts + * @param {Object} commands (optional) + * @return {Object} opts (parsed) + * @api public + */ +cli.parse = function (opts, command_def) { + var default_val, i, parsed = cli.options, seen, + catch_all = !opts; + opt_list = opts || {}; + commands = command_def; + command_list = commands || []; + if (commands && !Array.isArray(commands)) { + command_list = Object.keys(commands); + } + while (o = cli.next()) { + seen = false; + for (opt in opt_list) { + if (!(opt_list[opt] instanceof Array)) { + continue; + } + if (!opt_list[opt][0]) { + opt_list[opt][0] = opt; + } + if (o === opt || o === opt_list[opt][0]) { + seen = true; + if (opt_list[opt].length === 2) { + parsed[opt] = true; + break; + } + default_val = null; + if (opt_list[opt].length === 4) { + default_val = opt_list[opt][3]; + } + if (opt_list[opt][2] instanceof Array) { + for (i = 0, l = opt_list[opt][2].length; i < l; i++) { + if (typeof opt_list[opt][2][i] === 'number') { + opt_list[opt][2][i] += ''; + } + } + parsed[opt] = cli.getArrayValue(opt_list[opt][2], is_long ? null : default_val); + break; + } + if (opt_list[opt][2].toLowerCase) { + opt_list[opt][2] = opt_list[opt][2].toLowerCase(); + } + switch (opt_list[opt][2]) { + case 'string': case 1: case true: + parsed[opt] = cli.getValue(default_val); + break; + case 'int': case 'number': case 'num': + case 'time': case 'seconds': case 'secs': case 'minutes': case 'mins': + case 'x': case 'n': + parsed[opt] = cli.getInt(default_val); + break; + case 'float': case 'decimal': + parsed[opt] = cli.getFloat(default_val); + break; + case 'path': case 'file': case 'directory': case 'dir': + parsed[opt] = cli.getPath(default_val, opt_list[opt][2]); + break; + case 'email': + parsed[opt] = cli.getEmail(default_val); + break; + case 'url': case 'uri': case 'domain': case 'host': + parsed[opt] = cli.getUrl(default_val, opt_list[opt][2]); + break; + case 'ip': + parsed[opt] = cli.getIp(default_val); + break; + case 'bool': case 'boolean': case 'on': + parsed[opt] = true; + break; + case 'false': case 'off': case false: case 0: + parsed[opt] = false; + break; + default: + cli.fatal('Unknown opt type "' + opt_list[opt][2] + '"'); + } + break; + } + } + if (process.env.NODE_DISABLE_COLORS) { + no_color = true; + } + if (!seen) { + if (enable.help && (o === 'h' || o === 'help')) { + cli.getUsage(); + process.exit(); + } else if (enable.version && (o === 'v' || o === 'version')) { + if (cli.version == null) { + cli.parsePackageJson(); + } + console.error(cli.app + ' v' + cli.version); + process.exit(); + } else if (enable.daemon && (o === 'd' || o === 'daemon')) { + daemon_arg = cli.getArrayValue(['start','stop','restart','pid','log'], is_long ? null : 'start'); + continue; + } else if (enable.catchall && (o === 'c' || o === 'catch')) { + continue; + } else if (enable.status && (o === 'k' || o === 'no-color' || o === 'debug')) { + no_color = (o === 'k' || o === 'no-color'); + show_debug = o === 'debug'; + continue; + } else if (enable.timeout && (o === 't' || o === 'timeout')) { + var secs = cli.getInt(); + setTimeout(function () { + cli.fatal('Process timed out after ' + secs + 's'); + }, secs * 1000); + continue; + } else if (catch_all) { + parsed[o] = curr_val || true; + continue; + } + cli.fatal('Unknown option ' + full_opt); + } + } + //Fill the remaining options with their default value or null + for (opt in opt_list) { + default_val = opt_list[opt].length === 4 ? opt_list[opt][3] : null; + if (!(opt_list[opt] instanceof Array)) { + parsed[opt] = opt_list[opt]; + continue; + } else if (typeof parsed[opt] === 'undefined') { + parsed[opt] = default_val; + } + } + if (command_list.length) { + if (cli.args.length === 0) { + if (enable.help) { + cli.getUsage(); + } else { + cli.fatal('A command is required (' + command_list.join(', ') + ').'); + } + process.exit(1); + } else { + cli.command = cli.autocompleteCommand(cli.args.shift()); + } + } + cli.argc = cli.args.length; + return parsed; +}; + +/** + * Helper method for matching a command from the command list. + * + * @param {String} command + * @return {String} full_command + * @api public + */ +cli.autocompleteCommand = function (command) { + var list; + if (!(command_list instanceof Array)) { + list = Object.keys(command_list); + } else { + list = command_list; + } + var i, j = 0, c = command.length, tmp_list; + if (list.length === 0 || list.indexOf(command) !== -1) { + return command; + } + for (i = 0; i < c; i++) { + tmp_list = []; + l = list.length; + if (l <= 1) break; + for (j = 0; j < l; j++) + if (list[j].length >= i && list[j][i] === command[i]) + tmp_list.push(list[j]); + list = tmp_list; + } + l = list.length; + if (l === 1) { + return list[0]; + } else if (l === 0) { + cli.fatal('Unknown command "' + command + '"' + (enable.help ? '. Please see --help for more information' : '')); + } else { + list.sort(); + cli.fatal('The command "' + command + '" is ambiguous and could mean "' + list.join('", "') + '"'); + } +}; + +/** + * Adds methods to output styled status messages to stderr. + * + * Added methods are cli.info(msg), cli.error(msg), cli.ok(msg), and + * cli.debug(msg). + * + * To control status messages, use the 'status' plugin + * 1) debug() messages are hidden by default. Display them with + * the --debug opt. + * 2) to hide all status messages, use the -s or --silent opt. + * + * @api private + */ +cli.status = function (msg, type) { + var pre; + switch (type) { + case 'info': + pre = no_color ? 'INFO:' : '\x1B[33mINFO\x1B[0m:'; + break; + case 'debug': + pre = no_color ? 'DEBUG:' : '\x1B[36mDEBUG\x1B[0m:'; + break; + case 'error': + case 'fatal': + pre = no_color ? 'ERROR:' : '\x1B[31mERROR\x1B[0m:'; + break; + case 'ok': + pre = no_color ? 'OK:' : '\x1B[32mOK\x1B[0m:'; + break; + } + msg = pre + ' ' + msg; + if (type === 'fatal') { + console.error(msg); + process.exit(1); + } + if (enable.status && !show_debug && type === 'debug') { + return; + } + console.error(msg); +}; +['info','error','ok','debug','fatal'].forEach(function (type) { + cli[type] = function (msg) { + cli.status(msg, type); + }; +}); + +/** + * Sets the app name and version. + * + * Usage: + * setApp('myapp', '0.1.0'); + * setApp('./package.json'); //Pull name/version from package.json + * + * @param {String} name + * @return cli (for chaining) + * @api public + */ +cli.setApp = function (name, version) { + if (name.indexOf('package.json') !== -1) { + cli.parsePackageJson(name); + } else { + cli.app = name; + cli.version = version; + } + return cli; +}; + +/** + * Parses the version number from package.json. If no path is specified, cli + * will attempt to locate a package.json in ./, ../ or ../../ + * + * @param {String} path (optional) + * @api public + */ +cli.parsePackageJson = function (path) { + var parse_packagejson = function (path) { + var packagejson = JSON.parse(cli.native.fs.readFileSync(path, 'utf8')); + cli.version = packagejson.version; + cli.app = packagejson.name; + }; + var try_all = function (arr, func, err) { + for (var i = 0, l = arr.length; i < l; i++) { + try { + func(arr[i]); + return; + } catch (e) { + if (i === l-1) { + cli.fatal(err); + } + } + } + }; + try { + if (path) { + return parse_packagejson(path); + } + try_all([ + __dirname + '/package.json', + __dirname + '/../package.json', + __dirname + '/../../package.json' + ], parse_packagejson); + } catch (e) { + cli.fatal('Could not detect ' + cli.app + ' version'); + } +}; + +/** + * Sets the usage string - default is `app [OPTIONS] [ARGS]`. + * + * @param {String} u + * @return cli (for chaining) + * @api public + */ +cli.setUsage = function (u) { + usage = u; + return cli; +}; + +var pad = function (str, len) { + if (typeof len === 'undefined') { + len = str; + str = ''; + } + if (str.length < len) { + len -= str.length; + while (len--) str += ' '; + } + return str; +}; + +/** + * Automatically build usage information from the opts list. If the help + * plugin is enabled (default), this info is displayed with -h, --help. + * + * @api public + */ +cli.getUsage = function () { + var short, desc, optional, line, seen_opts = [], + switch_pad = cli.option_width; + + var trunc_desc = function (pref, desc, len) { + var pref_len = pref.length, + desc_len = cli.width - pref_len, + truncated = ''; + if (desc.length <= desc_len) { + return desc; + } + var desc_words = (desc+'').split(' '), chars = 0, word; + while (desc_words.length) { + truncated += (word = desc_words.shift()) + ' '; + chars += word.length; + if (desc_words.length && chars + desc_words[0].length > desc_len) { + truncated += '\n' + pad(pref_len); + chars = 0; + } + } + return truncated; + }; + + usage = usage || cli.app + ' [OPTIONS]' + (command_list.length ? ' ' : '') + ' [ARGS]'; + if (no_color) { + console.error('Usage:\n ' + usage); + console.error('Options: '); + } else { + console.error('\x1b[1mUsage\x1b[0m:\n ' + usage); + console.error('\n\x1b[1mOptions\x1b[0m: '); + } + for (opt in opt_list) { + + if (opt.length === 1) { + long = opt_list[opt][0]; + short = opt; + } else { + long = opt; + short = opt_list[opt][0]; + } + + //Parse opt_list + desc = opt_list[opt][1].trim(); + type = opt_list[opt].length >= 3 ? opt_list[opt][2] : null; + optional = opt_list[opt].length === 4 ? opt_list[opt][3] : null; + + //Build usage line + if (short === long) { + if (short.length === 1) { + line = ' -' + short; + } else { + line = ' --' + long; + } + } else { + line = ' -' + short + ', --' + long; + } + line += ' '; + + if (type) { + if (type instanceof Array) { + desc += '. VALUE must be either [' + type.join('|') + ']'; + type = 'VALUE'; + } + if (type === true || type === 1) { + type = long.toUpperCase(); + } + type = type.toUpperCase(); + if (type === 'FLOAT' || type === 'INT') { + type = 'NUMBER'; + } + line += optional ? '[' + type + ']' : type; + } + line = pad(line, switch_pad); + line += trunc_desc(line, desc); + line += optional ? ' (Default is ' + optional + ')' : ''; + console.error(line.replace('%s', '%\0s')); + + seen_opts.push(short); + seen_opts.push(long); + } + if (enable.timeout && seen_opts.indexOf('t') === -1 && seen_opts.indexOf('timeout') === -1) { + console.error(pad(' -t, --timeout N', switch_pad) + 'Exit if the process takes longer than N seconds'); + } + if (enable.status) { + if (seen_opts.indexOf('k') === -1 && seen_opts.indexOf('no-color') === -1) { + console.error(pad(' -k, --no-color', switch_pad) + 'Omit color from output'); + } + if (seen_opts.indexOf('debug') === -1) { + console.error(pad(' --debug', switch_pad) + 'Show debug information'); + } + } + if (enable.catchall && seen_opts.indexOf('c') === -1 && seen_opts.indexOf('catch') === -1) { + console.error(pad(' -c, --catch', switch_pad) + 'Catch unanticipated errors'); + } + if (enable.daemon && seen_opts.indexOf('d') === -1 && seen_opts.indexOf('daemon') === -1) { + console.error(pad(' -d, --daemon [ARG]', switch_pad) + 'Daemonize the process. Control the daemon using [start, stop, restart, log, pid]'); + } + if (enable.version && seen_opts.indexOf('v') === -1 && seen_opts.indexOf('version') === -1) { + console.error(pad(' -v, --version', switch_pad) + 'Display the current version'); + } + if (enable.help && seen_opts.indexOf('h') === -1 && seen_opts.indexOf('help') === -1) { + console.error(pad(' -h, --help', switch_pad) + 'Display help and usage details'); + } + if (command_list.length) { + console.error('\n\x1b[1mCommands\x1b[0m: '); + if (!Array.isArray(commands)) { + for (var c in commands) { + line = ' ' + pad(c, switch_pad - 2); + line += trunc_desc(line, commands[c]); + console.error(line); + } + } else { + command_list.sort(); + console.error(' ' + trunc_desc(' ', command_list.join(', '))); + } + } + process.exit(); +}; + +/** + * Generates an error message when an opt is incorrectly used. + * + * @param {String} expects (e.g. 'a value') + * @param {String} type (e.g. 'VALUE') + * @api public + */ +cli.getOptError = function (expects, type) { + var err = full_opt + ' expects ' + expects + + '. Use `' + cli.app + ' ' + full_opt + (is_long ? '=' : ' ') + type + '`'; + return err; +}; + +/** + * Gets the next opt value and validates it with an optional validation + * function. If validation fails or no value can be obtained, this method + * will return the default value (if specified) or exit with err_msg. + * + * @param {String} default_val + * @param {Function} validate_func + * @param {String} err_msg + * @api public + */ +cli.getValue = function (default_val, validate_func, err_msg) { + err_msg = err_msg || cli.getOptError('a value', 'VALUE'); + + var value; + + try { + if (curr_val) { + if (validate_func) { + curr_val = validate_func(curr_val); + } + return curr_val; + } + + //Grouped short opts aren't allowed to have values + if (short_tags.length) { + throw 'Short tags'; + } + + //If there's no args left or the next arg is an opt, return the + //default value (if specified) - otherwise fail + if (!argv.length || (argv[0].length === 1 && argv[0][0] === '-')) { + throw 'No value'; + } + + value = argv.shift(); + + if (value.match(/^[0-9]+$/)) { + value = parseInt(value, 10); + } + + //Run the value through a validation/transformation function if specified + if (validate_func) { + value = validate_func(value); + } + } catch (e) { + + //The value didn't pass the validation/transformation. Unshift the value and + //return the default value (if specified) + if (value) { + argv.unshift(value); + } + return default_val != null ? default_val : cli.fatal(err_msg); + } + return value; +}; + +cli.getInt = function (default_val) { + return cli.getValue(default_val, function (value) { + if (typeof value === 'number') return value; + if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))$/)) { + throw 'Invalid int'; + } + return parseInt(value); + }, cli.getOptError('a number', 'NUMBER')); +} + +cli.getFloat = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))?(?:\.[0-9]*)?$/)) { + throw 'Invalid float'; + } + return parseFloat(value, 10); + }, cli.getOptError('a number', 'NUMBER')); +} + +cli.getUrl = function (default_val, identifier) { + identifier = identifier || 'url'; + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/i)) { + throw 'Invalid URL'; + } + return value; + }, cli.getOptError('a ' + identifier, identifier.toUpperCase())); +} + +cli.getEmail = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/)) { + throw 'Invalid email'; + } + return value; + }, cli.getOptError('an email', 'EMAIL')); +} + +cli.getIp = function (default_val) { + return cli.getValue(default_val, function (value) { + if (!value.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/)) { + throw 'Invalid IP'; + } + return value; + }, cli.getOptError('an IP', 'IP')); +} + +cli.getPath = function (default_val, identifier) { + identifier = identifier || 'path'; + return cli.getValue(default_val, function (value) { + if (value.match(/[?*:;{}]/)) { + throw 'Invalid path'; + } + return value; + }, cli.getOptError('a ' + identifier, identifier.toUpperCase())); +} + +cli.getArrayValue = function (arr, default_val) { + return cli.getValue(default_val, function (value) { + if (arr.indexOf(value) === -1) { + throw 'Unexpected value'; + } + return value; + }, cli.getOptError('either [' + arr.join('|') + ']', 'VALUE')); +} + +/** + * Gets all data from STDIN (with optional encoding) and sends it to callback. + * + * @param {String} encoding (optional - default is 'utf8') + * @param {Function} callback + * @api public + */ +cli.withStdin = function (encoding, callback) { + if (typeof encoding === 'function') { + callback = encoding; + encoding = 'utf8'; + } + var stream = process.openStdin(), data = ''; + stream.setEncoding(encoding); + stream.on('data', function (chunk) { + data += chunk; + }); + stream.on('end', function () { + callback.apply(cli, [data]); + }); +}; + +/** + * Gets all data from STDIN, splits the data into lines and sends it + * to callback (callback isn't called until all of STDIN is read. To + * process each line as it's received, see the method below + * + * @param {Function} callback + * @api public + */ +cli.withStdinLines = function (callback) { + cli.withStdin(function (data) { + var sep = data.indexOf('\r\n') !== -1 ? '\r\n' : '\n'; + callback.apply(cli, [data.split(sep), sep]); + }); +}; + +/** + * Asynchronously reads a file line by line. When a line is received, + * callback is called with (line, sep) - when EOF is reached, callback + * receives (null, null, true) + * + * @param {String} file (optional - default is 'stdin') + * @param {String} encoding (optional - default is 'utf8') + * @param {Function} callback (line, sep, eof) + * @api public + */ +cli.withInput = function (file, encoding, callback) { + if (typeof encoding === 'function') { + callback = encoding; + encoding = 'utf8'; + } else if (typeof file === 'function') { + callback = file; + encoding = 'utf8'; + file = 'stdin'; + } + if (file === 'stdin') { + file = process.openStdin(); + } else { + try { + file = cli.native.fs.createReadStream(file); + file.on('error', cli.fatal); + } catch (e) { + return cli.fatal(e); + } + } + file.setEncoding(encoding); + var lines = [], data = '', eof, sep; + file.on('data', function (chunk) { + if (eof) return; + data += chunk; + if (!sep) { + if (data.indexOf('\r\n') !== -1) { + sep = '\r\n'; + } else if (data.indexOf('\n') !== -1) { + sep = '\n'; + } else { + last_line = data; + return; + } + } + lines = data.split(sep); + data = eof ? null : lines.pop(); + while (lines.length) { + callback.apply(cli, [lines.shift(), sep, false]); + } + }); + file.on('end', function () { + eof = true; + if (data.length) { + callback.apply(cli, [data, sep || '', false]); + } + callback.apply(cli, [null, null, true]); + }); +}; + +/** + * A method for creating and controlling a daemon. + * + * `arg` can be: + * start = daemonizes the process + * stop = stops the daemon if it is running + * restart = alias for stop -> start + * pid = outputs the daemon's PID if it is running + * log = outputs the daemon's log file (stdout + stderr) + * + * @param {String} arg (Optional - default is 'start') + * @param {Function} callback + * @api public + */ +cli.daemon = function (arg, callback) { + if (typeof daemon === 'undefined') { + cli.fatal('Daemon is not initialized'); + } + + if (typeof arg === 'function') { + callback = arg; + arg = 'start'; + } + + var lock_file = '/tmp/' + cli.app + '.pid', + log_file = '/tmp/' + cli.app + '.log'; + + var start = function () { + daemon.daemonize(log_file, lock_file, function (err) { + if (err) return cli.error('Error starting daemon: ' + err); + callback(); + }); + }; + + var stop = function () { + try { + cli.native.fs.readFileSync(lock_file); + } catch (e) { + return cli.error('Daemon is not running'); + }; + daemon.kill(lock_file, function (err, pid) { + if (err && err.errno === 3) { + return cli.error('Daemon is not running'); + } else if (err) { + return cli.error('Error stopping daemon: ' + err.errno); + } + cli.ok('Successfully stopped daemon with pid: ' + pid); + }); + }; + + switch(arg) { + case 'stop': + stop(); + break; + case 'restart': + daemon.stop(lock_file, function () { + start(); + }); + break; + case 'log': + try { + cli.native.fs.createReadStream(log_file, {encoding: 'utf8'}).pipe(process.stdout); + } catch (e) { + return cli.error('No daemon log file'); + }; + break; + case 'pid': + try { + var pid = cli.native.fs.readFileSync(lock_file, 'utf8'); + cli.native.fs.statSync('/proc/' + pid); + cli.info(pid); + } catch (e) { + return cli.error('Daemon is not running'); + }; + break; + default: + start(); + break; + } +} + +/** + * The main entry method. Calling cli.main() is only necessary in + * scripts that have daemon support enabled. `callback` receives (args, options) + * + * @param {Function} callback + * @api public + */ +cli.main = function (callback) { + var after = function () { + callback.apply(cli, [cli.args, cli.options]); + }; + if (enable.daemon && daemon_arg) { + cli.daemon(daemon_arg, after); + } else { + after(); + } +} + +/** + * Bind creationix's stack (https://github.com/creationix/stack). + * + * Create a simple middleware stack by calling: + * + * cli.createServer(middleware).listen(port); + * + * @return {Server} server + * @api public + */ +cli.createServer = function(/*layers*/) { + var defaultStackErrorHandler = function (req, res, err) { + if (err) { + console.error(err.stack); + res.writeHead(500, {"Content-Type": "text/plain"}); + return res.end(err.stack + "\n"); + } + res.writeHead(404, {"Content-Type": "text/plain"}); + res.end("Not Found\n"); + }; + var handle = error = defaultStackErrorHandler, + layers = Array.prototype.slice.call(arguments); + + //Allow createServer(a,b,c) and createServer([a,b,c]) + if (layers.length && layers[0] instanceof Array) { + layers = layers[0]; + } + layers.reverse().forEach(function (layer) { + var child = handle; + handle = function (req, res) { + try { + layer(req, res, function (err) { + if (err) return error(req, res, err); + child(req, res); + }); + } catch (err) { + error(req, res, err); + } + }; + }); + return cli.native.http.createServer(handle); +}; + +/** + * A wrapper for child_process.exec(). + * + * If the child_process exits successfully, `callback` receives an array of + * stdout lines. The current process exits if the child process has an error + * and `errback` isn't defined. + * + * @param {String} cmd + * @param {Function} callback (optional) + * @param {Function} errback (optional) + * @api public + */ +cli.exec = function (cmd, callback, errback) { + cli.native.child_process.exec(cmd, function (err, stdout, stderr) { + err = err || stderr; + if (err) { + if (errback) { + return errback(err, stdout); + } + return cli.fatal('exec() failed\n' + err); + } + if (callback) { + callback(stdout.split('\n')); + } + }); +}; + +/** + * Helper method for outputting a progress bar to the console. + * + * @param {Number} progress (0 <= progress <= 1) + * @api public + */ +var last_progress_call, progress_len = 74; +cli.progress = function (progress, decimals) { + if (progress < 0 || progress > 1 || isNaN(progress)) return; + if (!decimals) decimals = 0; + var now = (new Date()).getTime(); + if (last_progress_call && (now - last_progress_call) < 100 && progress !== 1) { + return; //Throttle progress calls + } + last_progress_call = now; + + + var barLength = Math.floor(progress_len * progress), + str = ''; + if (barLength == 0 && progress > 0) { + barLength = 1; + } + for (var i = 1; i <= progress_len; i++) { + str += i <= barLength ? '#' : ' '; + } + var pwr = Math.pow(10, decimals); + var percentage = Math.floor(progress * 100 * pwr) / pwr + '%'; + for (i = 0; i < decimals; i++) { + percentage += ' '; + } + cli.native.util.print('[' + str + '] ' + percentage + (progress === 1 ? '\n' : '\u000D')); +}; + +/** + * Helper method for outputting a spinner to the console. + * + * @param {String|Boolean} prefix (optional) + * @api public + */ +var spinnerInterval; +cli.spinner = function (prefix, end) { + if (end) { + cli.native.util.print('\u000D' + prefix); + return clearInterval(spinnerInterval); + } + prefix = prefix + ' ' || ''; + var spinner = ['-','\\','|','/'], i = 0, l = spinner.length; + spinnerInterval = setInterval(function () { + cli.native.util.print('\u000D' + prefix + spinner[i++]); + if (i == l) i = 0; + }, 200); +}; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/cat.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/cat.js new file mode 100755 index 000000000..14c4e79c4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/cat.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var output_file = function (file) { + cli.withInput(file, function (line, sep, eof) { + if (!eof) { + cli.output(line + sep); + } else if (cli.args.length) { + output_file(cli.args.shift()); + } + }); +}; + +if (cli.args.length) { + output_file(cli.args.shift()); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/command.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/command.js new file mode 100755 index 000000000..2f04491e7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/command.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +//The second (optional) argument of cli.parse() is a command list +//Type `./command.js --help` for usage info + +//cli enables auto-completion of commands (similiar to npm), e.g. all of +//the following are equivalent and result in "Command is: install": +// $ ./command.js install +// $ ./command.js inst +// $ ./command.js i + +cli.parse(null, ['install', 'test', 'edit', 'remove', 'uninstall', 'ls']); + +console.log('Command is: ' + cli.command); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/echo.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/echo.js new file mode 100755 index 000000000..dac9ccaf1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/echo.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +/* All of the following commands are equivalent and write `foo\tbar foo` to out.txt + $ ./echo.js -n -e --output=out.txt "foo\tbar" "foo" + $ ./echo.js --newline --escape --output "out.txt" "foo\tbar" "foo" + $ ./echo.js -ne --output=out.txt "foo\tbar" "foo" + $ ./echo.js -en --output="out.txt" "foo\tbar" "foo" +*/ + +var cli = require('cli'); + +cli.parse({ + newline: ['n', 'Do not output the trailing newline'], + escape: ['e', 'Enable interpretation of backslash escapes'], + separator: ['s', 'Separate arguments using this value', 'string', ' '], + output: [false, 'Write to FILE rather than the console', 'file'] +}); + +cli.main(function (args, options) { + var output = '', i, j, l, output_stream; + + if (this.argc) { + if (options.escape) { + var replace = {'\\n':'\n','\\r':'\r','\\t':'\t','\\e':'\e','\\v':'\v','\\f':'\f','\\c':'\c','\\b':'\b','\\a':'\a','\\\\':'\\'}; + var escape = function (str) { + string += ''; + for (j in replace) { + string = string.replace(i, replace[i]); + } + return string; + } + for (i = 0, l = this.argc; i < l; i++) { + args[i] = escape(args[i]); + } + options.separator = escape(options.separator); + } + output += args.join(options.separator); + } + + if (!options.newline) { + output += '\n'; + } + + try { + if (options.output) { + output_stream = this.native.fs.createWriteStream(options.output) + } else { + output_stream = process.stdout; + } + output_stream.write(output); + } catch (e) { + this.fatal('Could not write to output stream'); + } +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/glob.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/glob.js new file mode 100755 index 000000000..12585c01f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/glob.js @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +var cli = require('cli').enable('glob'); + +//Running `./glob.js *.js` will output a list of .js files in this directory +console.log(cli.args); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/long_desc.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/long_desc.js new file mode 100755 index 000000000..63632f4bb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/long_desc.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node + +var cli = require('../'); + +//You can (optionally) boost the width of output with: +//cli.width = 120; + +//You can also adjust the width of the options/command definitions +//cli.option_width = 25; + +var long_desc = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s ' + + 'standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make' + + ' a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, ' + + 'remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing ' + + 'Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions' + + ' of Lorem Ipsum.'; + +cli.parse({ + foo: ['f', long_desc] +}); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/progress.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/progress.js new file mode 100755 index 000000000..300c67405 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/progress.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var i = 0, interval = setInterval(function () { + cli.progress(++i / 100); + if (i === 100) { + clearInterval(interval); + cli.ok('Finished!'); + } +}, 50); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/sort.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/sort.js new file mode 100755 index 000000000..5d223133f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/sort.js @@ -0,0 +1,18 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +var options = cli.parse({ + numeric: ['n', 'Compare using a numeric sort'], + reverse: ['r', 'Reverse the results'] +}); + +cli.withStdinLines(function (lines, newline) { + lines.sort(!options.numeric ? null : function (a, b) { + return parseInt(a) > parseInt(b); + }); + if (options.reverse) { + lines.reverse(); + } + this.output(lines.join(newline)); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/spinner.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/spinner.js new file mode 100755 index 000000000..61000013a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/spinner.js @@ -0,0 +1,9 @@ +#!/usr/bin/env node + +var cli = require('cli'); + +cli.spinner('Working..'); + +setTimeout(function () { + cli.spinner('Working.. done!', true); //End the spinner +}, 3000); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.coffee b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.coffee new file mode 100755 index 000000000..cbf3b16e1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.coffee @@ -0,0 +1,27 @@ +#!/usr/bin/env coffee + +cli = require 'cli' + +cli.enable('daemon','status') + .setUsage('static.coffee [OPTIONS]') + +cli.parse { + log: ['l', 'Enable logging'] + port: ['p', 'Listen on this port', 'number', 8080] + serve: [false, 'Serve static files from PATH', 'path', './public'] +} + +middleware = [] + +cli.main (args, options) -> + + if options.log + @debug 'Enabling logging' + middleware.push require('creationix/log')() + + @debug 'Serving files from ' + options.serve + middleware.push require('creationix/static')('/', options.serve, 'index.html') + + server = @createServer(middleware).listen options.port + + @ok 'Listening on port ' + options.port \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.js new file mode 100755 index 000000000..eb6fd2481 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/examples/static.js @@ -0,0 +1,25 @@ +#!/usr/bin/env node + +var cli = require('cli').enable('status', 'daemon'); + +cli.parse({ + log: ['l', 'Enable logging'], + port: ['p', 'Listen on this port', 'number', 8080], + serve: [false, 'Serve static files from PATH', 'path', './public'] +}); + +cli.main(function (args, options) { + var server, middleware = []; + + if (options.log) { + this.debug('Enabling logging'); + middleware.push(require('creationix/log')()); + } + + this.debug('Serving files from ' + options.serve); + middleware.push(require('creationix/static')('/', options.serve, 'index.html')); + + server = this.createServer(middleware).listen(options.port); + + this.ok('Listening on port ' + options.port); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/index.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/index.js new file mode 100644 index 000000000..3966bd737 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/index.js @@ -0,0 +1 @@ +module.exports = require('./cli'); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore new file mode 100644 index 000000000..2af4b71c9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.npmignore @@ -0,0 +1,2 @@ +.*.swp +test/a/ diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml new file mode 100644 index 000000000..baa0031d5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/README.md new file mode 100644 index 000000000..cc6916451 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/README.md @@ -0,0 +1,250 @@ +# Glob + +Match files using the patterns the shell uses, like stars and stuff. + +This is a glob implementation in JavaScript. It uses the `minimatch` +library to do its matching. + +## Attention: node-glob users! + +The API has changed dramatically between 2.x and 3.x. This library is +now 100% JavaScript, and the integer flags have been replaced with an +options object. + +Also, there's an event emitter class, proper tests, and all the other +things you've come to expect from node modules. + +And best of all, no compilation! + +## Usage + +```javascript +var glob = require("glob") + +// options is optional +glob("**/*.js", options, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. +}) +``` + +## Features + +Please see the [minimatch +documentation](https://github.com/isaacs/minimatch) for more details. + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` +* [minimatch documentation](https://github.com/isaacs/minimatch) + +## glob(pattern, [options], cb) + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* `cb` {Function} + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Perform an asynchronous glob search. + +## glob.sync(pattern, [options]) + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* return: {Array} filenames found matching the pattern + +Perform a synchronous glob search. + +## Class: glob.Glob + +Create a Glob object by instanting the `glob.Glob` class. + +```javascript +var Glob = require("glob").Glob +var mg = new Glob(pattern, options, cb) +``` + +It's an EventEmitter, and starts walking the filesystem to find matches +immediately. + +### new glob.Glob(pattern, [options], [cb]) + +* `pattern` {String} pattern to search for +* `options` {Object} +* `cb` {Function} Called when an error occurs, or matches are found + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Note that if the `sync` flag is set in the options, then matches will +be immediately available on the `g.found` member. + +### Properties + +* `minimatch` The minimatch object that the glob uses. +* `options` The options object passed in. +* `error` The error encountered. When an error is encountered, the + glob object is in an undefined state, and should be discarded. +* `aborted` Boolean which is set to true when calling `abort()`. There + is no way at this time to continue a glob search after aborting, but + you can re-use the statCache to avoid having to duplicate syscalls. +* `statCache` Collection of all the stat results the glob search + performed. +* `cache` Convenience object. Each field has the following possible + values: + * `false` - Path does not exist + * `true` - Path exists + * `1` - Path exists, and is not a directory + * `2` - Path exists, and is a directory + * `[file, entries, ...]` - Path exists, is a directory, and the + array value is the results of `fs.readdir` + +### Events + +* `end` When the matching is finished, this is emitted with all the + matches found. If the `nonull` option is set, and no match was found, + then the `matches` list contains the original pattern. The matches + are sorted, unless the `nosort` flag is set. +* `match` Every time a match is found, this is emitted with the matched. +* `error` Emitted when an unexpected error is encountered, or whenever + any fs error occurs if `options.strict` is set. +* `abort` When `abort()` is called, this event is raised. + +### Methods + +* `abort` Stop the search. + +### Options + +All the options that can be passed to Minimatch can also be passed to +Glob to change pattern matching behavior. Also, some have been added, +or have glob-specific ramifications. + +All options are false by default, unless otherwise noted. + +All options are added to the glob object, as well. + +* `cwd` The current working directory in which to search. Defaults + to `process.cwd()`. +* `root` The place where patterns starting with `/` will be mounted + onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix + systems, and `C:\` or some such on Windows.) +* `dot` Include `.dot` files in normal matches and `globstar` matches. + Note that an explicit dot in a portion of the pattern will always + match dot files. +* `nomount` By default, a pattern starting with a forward-slash will be + "mounted" onto the root setting, so that a valid filesystem path is + returned. Set this flag to disable that behavior. +* `mark` Add a `/` character to directory matches. Note that this + requires additional stat calls. +* `nosort` Don't sort the results. +* `stat` Set to true to stat *all* results. This reduces performance + somewhat, and is completely unnecessary, unless `readdir` is presumed + to be an untrustworthy indicator of file existence. It will cause + ELOOP to be triggered one level sooner in the case of cyclical + symbolic links. +* `silent` When an unusual error is encountered + when attempting to read a directory, a warning will be printed to + stderr. Set the `silent` option to true to suppress these warnings. +* `strict` When an unusual error is encountered + when attempting to read a directory, the process will just continue on + in search of other matches. Set the `strict` option to raise an error + in these cases. +* `cache` See `cache` property above. Pass in a previously generated + cache object to save some fs calls. +* `statCache` A cache of results of filesystem information, to prevent + unnecessary stat calls. While it should not normally be necessary to + set this, you may pass the statCache from one glob() call to the + options object of another, if you know that the filesystem will not + change between calls. (See "Race Conditions" below.) +* `sync` Perform a synchronous glob search. +* `nounique` In some cases, brace-expanded patterns can result in the + same file showing up multiple times in the result set. By default, + this implementation prevents duplicates in the result set. + Set this flag to disable that behavior. +* `nonull` Set to never return an empty set, instead returning a set + containing the pattern itself. This is the default in glob(3). +* `nocase` Perform a case-insensitive match. Note that case-insensitive + filesystems will sometimes result in glob returning results that are + case-insensitively matched anyway, since readdir and stat will not + raise an error. +* `debug` Set to enable debug logging in minimatch and glob. +* `globDebug` Set to enable debug logging in glob, but not minimatch. + +## Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between node-glob and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. + +If an escaped pattern has no matches, and the `nonull` flag is set, +then glob returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + +## Windows + +**Please only use forward-slashes in glob expressions.** + +Though windows uses either `/` or `\` as its path separator, only `/` +characters are used by this glob implementation. You must use +forward-slashes **only** in glob expressions. Back-slashes will always +be interpreted as escape characters, not path separators. + +Results from absolute patterns such as `/foo/*` are mounted onto the +root setting using `path.join`. On windows, this will by default result +in `/foo/*` matching `C:\foo\bar.txt`. + +## Race Conditions + +Glob searching, by its very nature, is susceptible to race conditions, +since it relies on directory walking and such. + +As a result, it is possible that a file that exists when glob looks for +it may have been deleted or modified by the time it returns the result. + +As part of its internal implementation, this program caches all stat +and readdir calls that it makes, in order to cut down on system +overhead. However, this also makes it even more susceptible to races, +especially if the cache or statCache objects are reused between glob +calls. + +Users are thus advised not to use a glob result as a guarantee of +filesystem state in the face of rapid changes. For the vast majority +of operations, this is never a problem. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js new file mode 100644 index 000000000..be122df00 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js @@ -0,0 +1,9 @@ +var Glob = require("../").Glob + +var pattern = "test/a/**/[cg]/../[cg]" +console.log(pattern) + +var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) { + console.log("matches", matches) +}) +console.log("after") diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js new file mode 100644 index 000000000..327a425e4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js @@ -0,0 +1,9 @@ +var Glob = require("../").Glob + +var pattern = "{./*/*,/*,/usr/local/*}" +console.log(pattern) + +var mg = new Glob(pattern, {mark: true}, function (er, matches) { + console.log("matches", matches) +}) +console.log("after") diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js new file mode 100644 index 000000000..7903be18f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js @@ -0,0 +1,680 @@ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// readdir(PREFIX) as ENTRIES +// If fails, END +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $]) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $]) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + + + +module.exports = glob + +var fs = require("fs") +, minimatch = require("minimatch") +, Minimatch = minimatch.Minimatch +, inherits = require("inherits") +, EE = require("events").EventEmitter +, path = require("path") +, isDir = {} +, assert = require("assert").ok + +function glob (pattern, options, cb) { + if (typeof options === "function") cb = options, options = {} + if (!options) options = {} + + if (typeof options === "number") { + deprecated() + return + } + + var g = new Glob(pattern, options, cb) + return g.sync ? g.found : g +} + +glob.fnmatch = deprecated + +function deprecated () { + throw new Error("glob's interface has changed. Please see the docs.") +} + +glob.sync = globSync +function globSync (pattern, options) { + if (typeof options === "number") { + deprecated() + return + } + + options = options || {} + options.sync = true + return glob(pattern, options) +} + + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (!(this instanceof Glob)) { + return new Glob(pattern, options, cb) + } + + if (typeof options === "function") { + cb = options + options = null + } + + if (typeof cb === "function") { + this.on("error", cb) + this.on("end", function (matches) { + cb(null, matches) + }) + } + + options = options || {} + + this.EOF = {} + this._emitQueue = [] + + this.maxDepth = options.maxDepth || 1000 + this.maxLength = options.maxLength || Infinity + this.cache = options.cache || {} + this.statCache = options.statCache || {} + + this.changedCwd = false + var cwd = process.cwd() + if (!options.hasOwnProperty("cwd")) this.cwd = cwd + else { + this.cwd = options.cwd + this.changedCwd = path.resolve(options.cwd) !== cwd + } + + this.root = options.root || path.resolve(this.cwd, "/") + this.root = path.resolve(this.root) + if (process.platform === "win32") + this.root = this.root.replace(/\\/g, "/") + + this.nomount = !!options.nomount + + if (!pattern) { + throw new Error("must provide pattern") + } + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + this.strict = options.strict !== false + this.dot = !!options.dot + this.mark = !!options.mark + this.sync = !!options.sync + this.nounique = !!options.nounique + this.nonull = !!options.nonull + this.nosort = !!options.nosort + this.nocase = !!options.nocase + this.stat = !!options.stat + + this.debug = !!options.debug || !!options.globDebug + if (this.debug) + this.log = console.error + + this.silent = !!options.silent + + var mm = this.minimatch = new Minimatch(pattern, options) + this.options = mm.options + pattern = this.pattern = mm.pattern + + this.error = null + this.aborted = false + + // list of all the patterns that ** has resolved do, so + // we can avoid visiting multiple times. + this._globstars = {} + + EE.call(this) + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + this.minimatch.set.forEach(iterator.bind(this)) + function iterator (pattern, i, set) { + this._process(pattern, 0, i, function (er) { + if (er) this.emit("error", er) + if (-- n <= 0) this._finish() + }) + } +} + +Glob.prototype.log = function () {} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + + var nou = this.nounique + , all = nou ? [] : {} + + for (var i = 0, l = this.matches.length; i < l; i ++) { + var matches = this.matches[i] + this.log("matches[%d] =", i, matches) + // do like the shell, and spit out the literal glob + if (!matches) { + if (this.nonull) { + var literal = this.minimatch.globSet[i] + if (nou) all.push(literal) + else all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) all.push.apply(all, m) + else m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) all = Object.keys(all) + + if (!this.nosort) { + all = all.sort(this.nocase ? alphasorti : alphasort) + } + + if (this.mark) { + // at *some* point we statted all of these + all = all.map(function (m) { + var sc = this.cache[m] + if (!sc) + return m + var isDir = (Array.isArray(sc) || sc === 2) + if (isDir && m.slice(-1) !== "/") { + return m + "/" + } + if (!isDir && m.slice(-1) === "/") { + return m.replace(/\/+$/, "") + } + return m + }, this) + } + + this.log("emitting end", all) + + this.EOF = this.found = all + this.emitMatch(this.EOF) +} + +function alphasorti (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return alphasort(a, b) +} + +function alphasort (a, b) { + return a > b ? 1 : a < b ? -1 : 0 +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit("abort") +} + +Glob.prototype.pause = function () { + if (this.paused) return + if (this.sync) + this.emit("error", new Error("Can't pause/resume sync glob")) + this.paused = true + this.emit("pause") +} + +Glob.prototype.resume = function () { + if (!this.paused) return + if (this.sync) + this.emit("error", new Error("Can't pause/resume sync glob")) + this.paused = false + this.emit("resume") + this._processEmitQueue() + //process.nextTick(this.emit.bind(this, "resume")) +} + +Glob.prototype.emitMatch = function (m) { + if (!this.stat || this.statCache[m] || m === this.EOF) { + this._emitQueue.push(m) + this._processEmitQueue() + } else { + this._stat(m, function(exists, isDir) { + if (exists) { + this._emitQueue.push(m) + this._processEmitQueue() + } + }) + } +} + +Glob.prototype._processEmitQueue = function (m) { + while (!this._processingEmitQueue && + !this.paused) { + this._processingEmitQueue = true + var m = this._emitQueue.shift() + if (!m) { + this._processingEmitQueue = false + break + } + + this.log('emit!', m === this.EOF ? "end" : "match") + + this.emit(m === this.EOF ? "end" : "match", m) + this._processingEmitQueue = false + } +} + +Glob.prototype._process = function (pattern, depth, index, cb_) { + assert(this instanceof Glob) + + var cb = function cb (er, res) { + assert(this instanceof Glob) + if (this.paused) { + if (!this._processQueue) { + this._processQueue = [] + this.once("resume", function () { + var q = this._processQueue + this._processQueue = null + q.forEach(function (cb) { cb() }) + }) + } + this._processQueue.push(cb_.bind(this, er, res)) + } else { + cb_.call(this, er, res) + } + }.bind(this) + + if (this.aborted) return cb() + + if (depth > this.maxDepth) return cb() + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === "string") { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + prefix = pattern.join("/") + this._stat(prefix, function (exists, isDir) { + // either it's there, or it isn't. + // nothing more to do, either way. + if (exists) { + if (prefix && isAbsolute(prefix) && !this.nomount) { + if (prefix.charAt(0) === "/") { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + } + } + + if (process.platform === "win32") + prefix = prefix.replace(/\\/g, "/") + + this.matches[index] = this.matches[index] || {} + this.matches[index][prefix] = true + this.emitMatch(prefix) + } + return cb() + }) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's "absolute" like /foo/bar, + // or "relative" like "../baz" + prefix = pattern.slice(0, n) + prefix = prefix.join("/") + break + } + + // get the list of entries. + var read + if (prefix === null) read = "." + else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) { + if (!prefix || !isAbsolute(prefix)) { + prefix = path.join("/", prefix) + } + read = prefix = path.resolve(prefix) + + // if (process.platform === "win32") + // read = prefix = prefix.replace(/^[a-zA-Z]:|\\/g, "/") + + this.log('absolute: ', prefix, this.root, pattern, read) + } else { + read = prefix + } + + this.log('readdir(%j)', read, this.cwd, this.root) + + return this._readdir(read, function (er, entries) { + if (er) { + // not a directory! + // this means that, whatever else comes after this, it can never match + return cb() + } + + // globstar is special + if (pattern[n] === minimatch.GLOBSTAR) { + // test without the globstar, and with every child both below + // and replacing the globstar. + var s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ] + entries.forEach(function (e) { + if (e.charAt(0) === "." && !this.dot) return + // instead of the globstar + s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))) + // below the globstar + s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n))) + }, this) + + s = s.filter(function (pattern) { + var key = gsKey(pattern) + var seen = !this._globstars[key] + this._globstars[key] = true + return seen + }, this) + + if (!s.length) + return cb() + + // now asyncForEach over this + var l = s.length + , errState = null + s.forEach(function (gsPattern) { + this._process(gsPattern, depth + 1, index, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (--l <= 0) return cb() + }) + }, this) + + return + } + + // not a globstar + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = pattern[n] + var rawGlob = pattern[n]._glob + , dotOk = this.dot || rawGlob.charAt(0) === "." + + entries = entries.filter(function (e) { + return (e.charAt(0) !== "." || dotOk) && + e.match(pattern[n]) + }) + + // If n === pattern.length - 1, then there's no need for the extra stat + // *unless* the user has specified "mark" or "stat" explicitly. + // We know that they exist, since the readdir returned them. + if (n === pattern.length - 1 && + !this.mark && + !this.stat) { + entries.forEach(function (e) { + if (prefix) { + if (prefix !== "/") e = prefix + "/" + e + else e = prefix + e + } + if (e.charAt(0) === "/" && !this.nomount) { + e = path.join(this.root, e) + } + + if (process.platform === "win32") + e = e.replace(/\\/g, "/") + + this.matches[index] = this.matches[index] || {} + this.matches[index][e] = true + this.emitMatch(e) + }, this) + return cb.call(this) + } + + + // now test all the remaining entries as stand-ins for that part + // of the pattern. + var l = entries.length + , errState = null + if (l === 0) return cb() // no matches possible + entries.forEach(function (e) { + var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)) + this._process(p, depth + 1, index, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (--l === 0) return cb.call(this) + }) + }, this) + }) + +} + +function gsKey (pattern) { + return '**' + pattern.map(function (p) { + return (p === minimatch.GLOBSTAR) ? '**' : (''+p) + }).join('/') +} + +Glob.prototype._stat = function (f, cb) { + assert(this instanceof Glob) + var abs = f + if (f.charAt(0) === "/") { + abs = path.join(this.root, f) + } else if (this.changedCwd) { + abs = path.resolve(this.cwd, f) + } + + if (f.length > this.maxLength) { + var er = new Error("Path name too long") + er.code = "ENAMETOOLONG" + er.path = f + return this._afterStat(f, abs, cb, er) + } + + this.log('stat', [this.cwd, f, '=', abs]) + + if (!this.stat && this.cache.hasOwnProperty(f)) { + var exists = this.cache[f] + , isDir = exists && (Array.isArray(exists) || exists === 2) + if (this.sync) return cb.call(this, !!exists, isDir) + return process.nextTick(cb.bind(this, !!exists, isDir)) + } + + var stat = this.statCache[abs] + if (this.sync || stat) { + var er + try { + stat = fs.statSync(abs) + } catch (e) { + er = e + } + this._afterStat(f, abs, cb, er, stat) + } else { + fs.stat(abs, this._afterStat.bind(this, f, abs, cb)) + } +} + +Glob.prototype._afterStat = function (f, abs, cb, er, stat) { + var exists + assert(this instanceof Glob) + + if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) { + this.log("should be ENOTDIR, fake it") + + er = new Error("ENOTDIR, not a directory '" + abs + "'") + er.path = abs + er.code = "ENOTDIR" + stat = null + } + + var emit = !this.statCache[abs] + this.statCache[abs] = stat + + if (er || !stat) { + exists = false + } else { + exists = stat.isDirectory() ? 2 : 1 + if (emit) + this.emit('stat', f, stat) + } + this.cache[f] = this.cache[f] || exists + cb.call(this, !!exists, exists === 2) +} + +Glob.prototype._readdir = function (f, cb) { + assert(this instanceof Glob) + var abs = f + if (f.charAt(0) === "/") { + abs = path.join(this.root, f) + } else if (isAbsolute(f)) { + abs = f + } else if (this.changedCwd) { + abs = path.resolve(this.cwd, f) + } + + if (f.length > this.maxLength) { + var er = new Error("Path name too long") + er.code = "ENAMETOOLONG" + er.path = f + return this._afterReaddir(f, abs, cb, er) + } + + this.log('readdir', [this.cwd, f, abs]) + if (this.cache.hasOwnProperty(f)) { + var c = this.cache[f] + if (Array.isArray(c)) { + if (this.sync) return cb.call(this, null, c) + return process.nextTick(cb.bind(this, null, c)) + } + + if (!c || c === 1) { + // either ENOENT or ENOTDIR + var code = c ? "ENOTDIR" : "ENOENT" + , er = new Error((c ? "Not a directory" : "Not found") + ": " + f) + er.path = f + er.code = code + this.log(f, er) + if (this.sync) return cb.call(this, er) + return process.nextTick(cb.bind(this, er)) + } + + // at this point, c === 2, meaning it's a dir, but we haven't + // had to read it yet, or c === true, meaning it's *something* + // but we don't have any idea what. Need to read it, either way. + } + + if (this.sync) { + var er, entries + try { + entries = fs.readdirSync(abs) + } catch (e) { + er = e + } + return this._afterReaddir(f, abs, cb, er, entries) + } + + fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb)) +} + +Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) { + assert(this instanceof Glob) + if (entries && !er) { + this.cache[f] = entries + // if we haven't asked to stat everything for suresies, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. This also gets us one step + // further into ELOOP territory. + if (!this.mark && !this.stat) { + entries.forEach(function (e) { + if (f === "/") e = f + e + else e = f + "/" + e + this.cache[e] = true + }, this) + } + + return cb.call(this, er, entries) + } + + // now handle errors, and cache the information + if (er) switch (er.code) { + case "ENOTDIR": // totally normal. means it *does* exist. + this.cache[f] = 1 + return cb.call(this, er) + case "ENOENT": // not terribly unusual + case "ELOOP": + case "ENAMETOOLONG": + case "UNKNOWN": + this.cache[f] = false + return cb.call(this, er) + default: // some unusual error. Treat as failure. + this.cache[f] = false + if (this.strict) this.emit("error", er) + if (!this.silent) console.error("glob error", er) + return cb.call(this, er) + } +} + +var isAbsolute = process.platform === "win32" ? absWin : absUnix + +function absWin (p) { + if (absUnix(p)) return true + // pull off the device/UNC bit from a windows path. + // from node's lib/path.js + var splitDeviceRe = + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/ + , result = splitDeviceRe.exec(p) + , device = result[1] || '' + , isUnc = device && device.charAt(1) !== ':' + , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute + + return isAbsolute +} + +function absUnix (p) { + return p.charAt(0) === "/" || p === "" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/LICENSE new file mode 100644 index 000000000..dea3013d6 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/LICENSE @@ -0,0 +1,16 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md new file mode 100644 index 000000000..b1c566585 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md @@ -0,0 +1,42 @@ +Browser-friendly inheritance fully compatible with standard node.js +[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). + +This package exports standard `inherits` from node.js `util` module in +node environment, but also provides alternative browser-friendly +implementation through [browser +field](https://gist.github.com/shtylman/4339901). Alternative +implementation is a literal copy of standard one located in standalone +module to avoid requiring of `util`. It also has a shim for old +browsers with no `Object.create` support. + +While keeping you sure you are using standard `inherits` +implementation in node.js environment, it allows bundlers such as +[browserify](https://github.com/substack/node-browserify) to not +include full `util` package to your client code if all you need is +just `inherits` function. It worth, because browser shim for `util` +package is large and `inherits` is often the single function you need +from it. + +It's recommended to use this package instead of +`require('util').inherits` for any code that has chances to be used +not only in node.js but in browser too. + +## usage + +```js +var inherits = require('inherits'); +// then use exactly as the standard one +``` + +## note on version ~1.0 + +Version ~1.0 had completely different motivation and is not compatible +neither with 2.0 nor with standard node.js `inherits`. + +If you are using version ~1.0 and planning to switch to ~2.0, be +careful: + +* new version uses `super_` instead of `super` for referencing + superclass +* new version overwrites current prototype while old one preserves any + existing fields on it diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js new file mode 100644 index 000000000..29f5e24f5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js @@ -0,0 +1 @@ +module.exports = require('util').inherits diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits_browser.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits_browser.js new file mode 100644 index 000000000..c1e78a75e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits_browser.js @@ -0,0 +1,23 @@ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json new file mode 100644 index 000000000..3c5a3c735 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json @@ -0,0 +1,36 @@ +{ + "name": "inherits", + "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", + "version": "2.0.1", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented", + "inherits", + "browser", + "browserify" + ], + "main": "./inherits.js", + "browser": "./inherits_browser.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/inherits" + }, + "license": "ISC", + "scripts": { + "test": "node test" + }, + "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n superclass\n* new version overwrites current prototype while old one preserves any\n existing fields on it\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/inherits/issues" + }, + "_id": "inherits@2.0.1", + "dist": { + "shasum": "e806d0cf3ab85425c667b15ccbda1c8f7819da84" + }, + "_from": "inherits@2", + "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/test.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/test.js new file mode 100644 index 000000000..fc53012d3 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/test.js @@ -0,0 +1,25 @@ +var inherits = require('./inherits.js') +var assert = require('assert') + +function test(c) { + assert(c.constructor === Child) + assert(c.constructor.super_ === Parent) + assert(Object.getPrototypeOf(c) === Child.prototype) + assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype) + assert(c instanceof Child) + assert(c instanceof Parent) +} + +function Child() { + Parent.call(this) + test(this) +} + +function Parent() {} + +inherits(Child, Parent) + +var c = new Child +test(c) + +console.log('ok') diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/package.json new file mode 100644 index 000000000..db6f731cf --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/package.json @@ -0,0 +1,42 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "name": "glob", + "description": "a little globber", + "version": "3.2.7", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-glob.git" + }, + "main": "glob.js", + "engines": { + "node": "*" + }, + "dependencies": { + "minimatch": "~0.2.11", + "inherits": "2" + }, + "devDependencies": { + "tap": "~0.4.0", + "mkdirp": "0", + "rimraf": "1" + }, + "scripts": { + "test": "tap test/*.js" + }, + "license": "BSD", + "readme": "# Glob\n\nMatch files using the patterns the shell uses, like stars and stuff.\n\nThis is a glob implementation in JavaScript. It uses the `minimatch`\nlibrary to do its matching.\n\n## Attention: node-glob users!\n\nThe API has changed dramatically between 2.x and 3.x. This library is\nnow 100% JavaScript, and the integer flags have been replaced with an\noptions object.\n\nAlso, there's an event emitter class, proper tests, and all the other\nthings you've come to expect from node modules.\n\nAnd best of all, no compilation!\n\n## Usage\n\n```javascript\nvar glob = require(\"glob\")\n\n// options is optional\nglob(\"**/*.js\", options, function (er, files) {\n // files is an array of filenames.\n // If the `nonull` option is set, and nothing\n // was found, then files is [\"**/*.js\"]\n // er is an error object or null.\n})\n```\n\n## Features\n\nPlease see the [minimatch\ndocumentation](https://github.com/isaacs/minimatch) for more details.\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n* [minimatch documentation](https://github.com/isaacs/minimatch)\n\n## glob(pattern, [options], cb)\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* `cb` {Function}\n * `err` {Error | null}\n * `matches` {Array} filenames found matching the pattern\n\nPerform an asynchronous glob search.\n\n## glob.sync(pattern, [options])\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* return: {Array} filenames found matching the pattern\n\nPerform a synchronous glob search.\n\n## Class: glob.Glob\n\nCreate a Glob object by instanting the `glob.Glob` class.\n\n```javascript\nvar Glob = require(\"glob\").Glob\nvar mg = new Glob(pattern, options, cb)\n```\n\nIt's an EventEmitter, and starts walking the filesystem to find matches\nimmediately.\n\n### new glob.Glob(pattern, [options], [cb])\n\n* `pattern` {String} pattern to search for\n* `options` {Object}\n* `cb` {Function} Called when an error occurs, or matches are found\n * `err` {Error | null}\n * `matches` {Array} filenames found matching the pattern\n\nNote that if the `sync` flag is set in the options, then matches will\nbe immediately available on the `g.found` member.\n\n### Properties\n\n* `minimatch` The minimatch object that the glob uses.\n* `options` The options object passed in.\n* `error` The error encountered. When an error is encountered, the\n glob object is in an undefined state, and should be discarded.\n* `aborted` Boolean which is set to true when calling `abort()`. There\n is no way at this time to continue a glob search after aborting, but\n you can re-use the statCache to avoid having to duplicate syscalls.\n* `statCache` Collection of all the stat results the glob search\n performed.\n* `cache` Convenience object. Each field has the following possible\n values:\n * `false` - Path does not exist\n * `true` - Path exists\n * `1` - Path exists, and is not a directory\n * `2` - Path exists, and is a directory\n * `[file, entries, ...]` - Path exists, is a directory, and the\n array value is the results of `fs.readdir`\n\n### Events\n\n* `end` When the matching is finished, this is emitted with all the\n matches found. If the `nonull` option is set, and no match was found,\n then the `matches` list contains the original pattern. The matches\n are sorted, unless the `nosort` flag is set.\n* `match` Every time a match is found, this is emitted with the matched.\n* `error` Emitted when an unexpected error is encountered, or whenever\n any fs error occurs if `options.strict` is set.\n* `abort` When `abort()` is called, this event is raised.\n\n### Methods\n\n* `abort` Stop the search.\n\n### Options\n\nAll the options that can be passed to Minimatch can also be passed to\nGlob to change pattern matching behavior. Also, some have been added,\nor have glob-specific ramifications.\n\nAll options are false by default, unless otherwise noted.\n\nAll options are added to the glob object, as well.\n\n* `cwd` The current working directory in which to search. Defaults\n to `process.cwd()`.\n* `root` The place where patterns starting with `/` will be mounted\n onto. Defaults to `path.resolve(options.cwd, \"/\")` (`/` on Unix\n systems, and `C:\\` or some such on Windows.)\n* `dot` Include `.dot` files in normal matches and `globstar` matches.\n Note that an explicit dot in a portion of the pattern will always\n match dot files.\n* `nomount` By default, a pattern starting with a forward-slash will be\n \"mounted\" onto the root setting, so that a valid filesystem path is\n returned. Set this flag to disable that behavior.\n* `mark` Add a `/` character to directory matches. Note that this\n requires additional stat calls.\n* `nosort` Don't sort the results.\n* `stat` Set to true to stat *all* results. This reduces performance\n somewhat, and is completely unnecessary, unless `readdir` is presumed\n to be an untrustworthy indicator of file existence. It will cause\n ELOOP to be triggered one level sooner in the case of cyclical\n symbolic links.\n* `silent` When an unusual error is encountered\n when attempting to read a directory, a warning will be printed to\n stderr. Set the `silent` option to true to suppress these warnings.\n* `strict` When an unusual error is encountered\n when attempting to read a directory, the process will just continue on\n in search of other matches. Set the `strict` option to raise an error\n in these cases.\n* `cache` See `cache` property above. Pass in a previously generated\n cache object to save some fs calls.\n* `statCache` A cache of results of filesystem information, to prevent\n unnecessary stat calls. While it should not normally be necessary to\n set this, you may pass the statCache from one glob() call to the\n options object of another, if you know that the filesystem will not\n change between calls. (See \"Race Conditions\" below.)\n* `sync` Perform a synchronous glob search.\n* `nounique` In some cases, brace-expanded patterns can result in the\n same file showing up multiple times in the result set. By default,\n this implementation prevents duplicates in the result set.\n Set this flag to disable that behavior.\n* `nonull` Set to never return an empty set, instead returning a set\n containing the pattern itself. This is the default in glob(3).\n* `nocase` Perform a case-insensitive match. Note that case-insensitive\n filesystems will sometimes result in glob returning results that are\n case-insensitively matched anyway, since readdir and stat will not\n raise an error.\n* `debug` Set to enable debug logging in minimatch and glob.\n* `globDebug` Set to enable debug logging in glob, but not minimatch.\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between node-glob and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen glob returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`glob.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n## Windows\n\n**Please only use forward-slashes in glob expressions.**\n\nThough windows uses either `/` or `\\` as its path separator, only `/`\ncharacters are used by this glob implementation. You must use\nforward-slashes **only** in glob expressions. Back-slashes will always\nbe interpreted as escape characters, not path separators.\n\nResults from absolute patterns such as `/foo/*` are mounted onto the\nroot setting using `path.join`. On windows, this will by default result\nin `/foo/*` matching `C:\\foo\\bar.txt`.\n\n## Race Conditions\n\nGlob searching, by its very nature, is susceptible to race conditions,\nsince it relies on directory walking and such.\n\nAs a result, it is possible that a file that exists when glob looks for\nit may have been deleted or modified by the time it returns the result.\n\nAs part of its internal implementation, this program caches all stat\nand readdir calls that it makes, in order to cut down on system\noverhead. However, this also makes it even more susceptible to races,\nespecially if the cache or statCache objects are reused between glob\ncalls.\n\nUsers are thus advised not to use a glob result as a guarantee of\nfilesystem state in the face of rapid changes. For the vast majority\nof operations, this is never a problem.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-glob/issues" + }, + "_id": "glob@3.2.7", + "dist": { + "shasum": "10cfd4b5028edd93249f7bc2297449b398ee9d7f" + }, + "_from": "glob@>= 3.1.4", + "_resolved": "https://registry.npmjs.org/glob/-/glob-3.2.7.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js new file mode 100644 index 000000000..245afafda --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js @@ -0,0 +1,176 @@ +// just a little pre-run script to set up the fixtures. +// zz-finish cleans it up + +var mkdirp = require("mkdirp") +var path = require("path") +var i = 0 +var tap = require("tap") +var fs = require("fs") +var rimraf = require("rimraf") + +var files = +[ "a/.abcdef/x/y/z/a" +, "a/abcdef/g/h" +, "a/abcfed/g/h" +, "a/b/c/d" +, "a/bc/e/f" +, "a/c/d/c/b" +, "a/cb/e/f" +] + +var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c") +var symlinkFrom = "../.." + +files = files.map(function (f) { + return path.resolve(__dirname, f) +}) + +tap.test("remove fixtures", function (t) { + rimraf(path.resolve(__dirname, "a"), function (er) { + t.ifError(er, "remove fixtures") + t.end() + }) +}) + +files.forEach(function (f) { + tap.test(f, function (t) { + var d = path.dirname(f) + mkdirp(d, 0755, function (er) { + if (er) { + t.fail(er) + return t.bailout() + } + fs.writeFile(f, "i like tests", function (er) { + t.ifError(er, "make file") + t.end() + }) + }) + }) +}) + +if (process.platform !== "win32") { + tap.test("symlinky", function (t) { + var d = path.dirname(symlinkTo) + console.error("mkdirp", d) + mkdirp(d, 0755, function (er) { + t.ifError(er) + fs.symlink(symlinkFrom, symlinkTo, "dir", function (er) { + t.ifError(er, "make symlink") + t.end() + }) + }) + }) +} + +;["foo","bar","baz","asdf","quux","qwer","rewq"].forEach(function (w) { + w = "/tmp/glob-test/" + w + tap.test("create " + w, function (t) { + mkdirp(w, function (er) { + if (er) + throw er + t.pass(w) + t.end() + }) + }) +}) + + +// generate the bash pattern test-fixtures if possible +if (process.platform === "win32" || !process.env.TEST_REGEN) { + console.error("Windows, or TEST_REGEN unset. Using cached fixtures.") + return +} + +var spawn = require("child_process").spawn; +var globs = + // put more patterns here. + // anything that would be directly in / should be in /tmp/glob-test + ["test/a/*/+(c|g)/./d" + ,"test/a/**/[cg]/../[cg]" + ,"test/a/{b,c,d,e,f}/**/g" + ,"test/a/b/**" + ,"test/**/g" + ,"test/a/abc{fed,def}/g/h" + ,"test/a/abc{fed/g,def}/**/" + ,"test/a/abc{fed/g,def}/**///**/" + ,"test/**/a/**/" + ,"test/+(a|b|c)/a{/,bc*}/**" + ,"test/*/*/*/f" + ,"test/**/f" + ,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**" + ,"{./*/*,/tmp/glob-test/*}" + ,"{/tmp/glob-test/*,*}" // evil owl face! how you taunt me! + ,"test/a/!(symlink)/**" + ] +var bashOutput = {} +var fs = require("fs") + +globs.forEach(function (pattern) { + tap.test("generate fixture " + pattern, function (t) { + var cmd = "shopt -s globstar && " + + "shopt -s extglob && " + + "shopt -s nullglob && " + + // "shopt >&2; " + + "eval \'for i in " + pattern + "; do echo $i; done\'" + var cp = spawn("bash", ["-c", cmd], { cwd: path.dirname(__dirname) }) + var out = [] + cp.stdout.on("data", function (c) { + out.push(c) + }) + cp.stderr.pipe(process.stderr) + cp.on("close", function (code) { + out = flatten(out) + if (!out) + out = [] + else + out = cleanResults(out.split(/\r*\n/)) + + bashOutput[pattern] = out + t.notOk(code, "bash test should finish nicely") + t.end() + }) + }) +}) + +tap.test("save fixtures", function (t) { + var fname = path.resolve(__dirname, "bash-results.json") + var data = JSON.stringify(bashOutput, null, 2) + "\n" + fs.writeFile(fname, data, function (er) { + t.ifError(er) + t.end() + }) +}) + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/') + }) +} + +function flatten (chunks) { + var s = 0 + chunks.forEach(function (c) { s += c.length }) + var out = new Buffer(s) + s = 0 + chunks.forEach(function (c) { + c.copy(out, s) + s += c.length + }) + + return out.toString().trim() +} + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js new file mode 100644 index 000000000..239ed1a9c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js @@ -0,0 +1,63 @@ +// basic test +// show that it does the same thing by default as the shell. +var tap = require("tap") +, child_process = require("child_process") +, bashResults = require("./bash-results.json") +, globs = Object.keys(bashResults) +, glob = require("../") +, path = require("path") + +// run from the root of the project +// this is usually where you're at anyway, but be sure. +process.chdir(path.resolve(__dirname, "..")) + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} + +globs.forEach(function (pattern) { + var expect = bashResults[pattern] + // anything regarding the symlink thing will fail on windows, so just skip it + if (process.platform === "win32" && + expect.some(function (m) { + return /\/symlink\//.test(m) + })) + return + + tap.test(pattern, function (t) { + glob(pattern, function (er, matches) { + if (er) + throw er + + // sort and unmark, just to match the shell results + matches = cleanResults(matches) + + t.deepEqual(matches, expect, pattern) + t.end() + }) + }) + + tap.test(pattern + " sync", function (t) { + var matches = cleanResults(glob.sync(pattern)) + + t.deepEqual(matches, expect, "should match shell") + t.end() + }) +}) + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:[\/\\]+/, '/').replace(/[\\\/]+/g, '/') + }) +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json new file mode 100644 index 000000000..593215cd9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json @@ -0,0 +1,350 @@ +{ + "test/a/*/+(c|g)/./d": [ + "test/a/b/c/./d" + ], + "test/a/**/[cg]/../[cg]": [ + "test/a/abcdef/g/../g", + "test/a/abcfed/g/../g", + "test/a/b/c/../c", + "test/a/c/../c", + "test/a/c/d/c/../c", + "test/a/symlink/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c" + ], + "test/a/{b,c,d,e,f}/**/g": [], + "test/a/b/**": [ + "test/a/b", + "test/a/b/c", + "test/a/b/c/d" + ], + "test/**/g": [ + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/a/abc{fed,def}/g/h": [ + "test/a/abcdef/g/h", + "test/a/abcfed/g/h" + ], + "test/a/abc{fed/g,def}/**/": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/a/abc{fed/g,def}/**///**/": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/**/a/**/": [ + "test/a", + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/b", + "test/a/b/c", + "test/a/bc", + "test/a/bc/e", + "test/a/c", + "test/a/c/d", + "test/a/c/d/c", + "test/a/cb", + "test/a/cb/e", + "test/a/symlink", + "test/a/symlink/a", + "test/a/symlink/a/b", + "test/a/symlink/a/b/c", + "test/a/symlink/a/b/c/a", + "test/a/symlink/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b" + ], + "test/+(a|b|c)/a{/,bc*}/**": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcdef/g/h", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/abcfed/g/h" + ], + "test/*/*/*/f": [ + "test/a/bc/e/f", + "test/a/cb/e/f" + ], + "test/**/f": [ + "test/a/bc/e/f", + "test/a/cb/e/f" + ], + "test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**": [ + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c" + ], + "{./*/*,/tmp/glob-test/*}": [ + "./examples/g.js", + "./examples/usr-local.js", + "./node_modules/inherits", + "./node_modules/minimatch", + "./node_modules/mkdirp", + "./node_modules/rimraf", + "./node_modules/tap", + "./test/00-setup.js", + "./test/a", + "./test/bash-comparison.js", + "./test/bash-results.json", + "./test/cwd-test.js", + "./test/globstar-match.js", + "./test/mark.js", + "./test/new-glob-optional-options.js", + "./test/nocase-nomagic.js", + "./test/pause-resume.js", + "./test/root-nomount.js", + "./test/root.js", + "./test/stat.js", + "./test/zz-cleanup.js", + "/tmp/glob-test/asdf", + "/tmp/glob-test/bar", + "/tmp/glob-test/baz", + "/tmp/glob-test/foo", + "/tmp/glob-test/quux", + "/tmp/glob-test/qwer", + "/tmp/glob-test/rewq" + ], + "{/tmp/glob-test/*,*}": [ + "/tmp/glob-test/asdf", + "/tmp/glob-test/bar", + "/tmp/glob-test/baz", + "/tmp/glob-test/foo", + "/tmp/glob-test/quux", + "/tmp/glob-test/qwer", + "/tmp/glob-test/rewq", + "examples", + "glob.js", + "LICENSE", + "node_modules", + "package.json", + "README.md", + "test" + ], + "test/a/!(symlink)/**": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcdef/g/h", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/abcfed/g/h", + "test/a/b", + "test/a/b/c", + "test/a/b/c/d", + "test/a/bc", + "test/a/bc/e", + "test/a/bc/e/f", + "test/a/c", + "test/a/c/d", + "test/a/c/d/c", + "test/a/c/d/c/b", + "test/a/cb", + "test/a/cb/e", + "test/a/cb/e/f" + ] +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js new file mode 100644 index 000000000..352c27efa --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js @@ -0,0 +1,55 @@ +var tap = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +tap.test("changing cwd and searching for **/d", function (t) { + var glob = require('../') + var path = require('path') + t.test('.', function (t) { + glob('**/d', function (er, matches) { + t.ifError(er) + t.like(matches, [ 'a/b/c/d', 'a/c/d' ]) + t.end() + }) + }) + + t.test('a', function (t) { + glob('**/d', {cwd:path.resolve('a')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'b/c/d', 'c/d' ]) + t.end() + }) + }) + + t.test('a/b', function (t) { + glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'c/d' ]) + t.end() + }) + }) + + t.test('a/b/', function (t) { + glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'c/d' ]) + t.end() + }) + }) + + t.test('.', function (t) { + glob('**/d', {cwd: process.cwd()}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'a/b/c/d', 'a/c/d' ]) + t.end() + }) + }) + + t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() + }) + + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/globstar-match.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/globstar-match.js new file mode 100644 index 000000000..9b234fa2a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/globstar-match.js @@ -0,0 +1,19 @@ +var Glob = require("../glob.js").Glob +var test = require('tap').test + +test('globstar should not have dupe matches', function(t) { + var pattern = 'a/**/[gh]' + var g = new Glob(pattern, { cwd: __dirname }) + var matches = [] + g.on('match', function(m) { + console.error('match %j', m) + matches.push(m) + }) + g.on('end', function(set) { + console.error('set', set) + matches = matches.sort() + set = set.sort() + t.same(matches, set, 'should have same set of matches') + t.end() + }) +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js new file mode 100644 index 000000000..ed68a335c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js @@ -0,0 +1,74 @@ +var test = require("tap").test +var glob = require('../') +process.chdir(__dirname) + +test("mark, no / on pattern", function (t) { + glob("a/*", {mark: true}, function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + + if (process.platform !== "win32") + expect.push('a/symlink/') + + t.same(results, expect) + t.end() + }) +}) + +test("mark=false, no / on pattern", function (t) { + glob("a/*", function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef', + 'a/abcfed', + 'a/b', + 'a/bc', + 'a/c', + 'a/cb' ] + + if (process.platform !== "win32") + expect.push('a/symlink') + t.same(results, expect) + t.end() + }) +}) + +test("mark=true, / on pattern", function (t) { + glob("a/*/", {mark: true}, function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + if (process.platform !== "win32") + expect.push('a/symlink/') + t.same(results, expect) + t.end() + }) +}) + +test("mark=false, / on pattern", function (t) { + glob("a/*/", function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + if (process.platform !== "win32") + expect.push('a/symlink/') + t.same(results, expect) + t.end() + }) +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/new-glob-optional-options.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/new-glob-optional-options.js new file mode 100644 index 000000000..3e7dc5acb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/new-glob-optional-options.js @@ -0,0 +1,10 @@ +var Glob = require('../glob.js').Glob; +var test = require('tap').test; + +test('new glob, with cb, and no options', function (t) { + new Glob(__filename, function(er, results) { + if (er) throw er; + t.same(results, [__filename]); + t.end(); + }); +}); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/nocase-nomagic.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/nocase-nomagic.js new file mode 100644 index 000000000..2503f2310 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/nocase-nomagic.js @@ -0,0 +1,113 @@ +var fs = require('fs'); +var test = require('tap').test; +var glob = require('../'); + +test('mock fs', function(t) { + var stat = fs.stat + var statSync = fs.statSync + var readdir = fs.readdir + var readdirSync = fs.readdirSync + + function fakeStat(path) { + var ret + switch (path.toLowerCase()) { + case '/tmp': case '/tmp/': + ret = { isDirectory: function() { return true } } + break + case '/tmp/a': + ret = { isDirectory: function() { return false } } + break + } + return ret + } + + fs.stat = function(path, cb) { + var f = fakeStat(path); + if (f) { + process.nextTick(function() { + cb(null, f) + }) + } else { + stat.call(fs, path, cb) + } + } + + fs.statSync = function(path) { + return fakeStat(path) || statSync.call(fs, path) + } + + function fakeReaddir(path) { + var ret + switch (path.toLowerCase()) { + case '/tmp': case '/tmp/': + ret = [ 'a', 'A' ] + break + case '/': + ret = ['tmp', 'tMp', 'tMP', 'TMP'] + } + return ret + } + + fs.readdir = function(path, cb) { + var f = fakeReaddir(path) + if (f) + process.nextTick(function() { + cb(null, f) + }) + else + readdir.call(fs, path, cb) + } + + fs.readdirSync = function(path) { + return fakeReaddir(path) || readdirSync.call(fs, path) + } + + t.pass('mocked') + t.end() +}) + +test('nocase, nomagic', function(t) { + var n = 2 + var want = [ '/TMP/A', + '/TMP/a', + '/tMP/A', + '/tMP/a', + '/tMp/A', + '/tMp/a', + '/tmp/A', + '/tmp/a' ] + glob('/tmp/a', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + if (--n === 0) t.end() + }) + glob('/tmp/A', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + if (--n === 0) t.end() + }) +}) + +test('nocase, with some magic', function(t) { + t.plan(2) + var want = [ '/TMP/A', + '/TMP/a', + '/tMP/A', + '/tMP/a', + '/tMp/A', + '/tMp/a', + '/tmp/A', + '/tmp/a' ] + glob('/tmp/*', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + }) + glob('/tmp/*', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + }) +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js new file mode 100644 index 000000000..e1ffbab1c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js @@ -0,0 +1,73 @@ +// show that no match events happen while paused. +var tap = require("tap") +, child_process = require("child_process") +// just some gnarly pattern with lots of matches +, pattern = "test/a/!(symlink)/**" +, bashResults = require("./bash-results.json") +, patterns = Object.keys(bashResults) +, glob = require("../") +, Glob = glob.Glob +, path = require("path") + +// run from the root of the project +// this is usually where you're at anyway, but be sure. +process.chdir(path.resolve(__dirname, "..")) + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/') + }) +} + +var globResults = [] +tap.test("use a Glob object, and pause/resume it", function (t) { + var g = new Glob(pattern) + , paused = false + , res = [] + , expect = bashResults[pattern] + + g.on("pause", function () { + console.error("pause") + }) + + g.on("resume", function () { + console.error("resume") + }) + + g.on("match", function (m) { + t.notOk(g.paused, "must not be paused") + globResults.push(m) + g.pause() + t.ok(g.paused, "must be paused") + setTimeout(g.resume.bind(g), 10) + }) + + g.on("end", function (matches) { + t.pass("reached glob end") + globResults = cleanResults(globResults) + matches = cleanResults(matches) + t.deepEqual(matches, globResults, + "end event matches should be the same as match events") + + t.deepEqual(matches, expect, + "glob matches should be the same as bash results") + + t.end() + }) +}) + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js new file mode 100644 index 000000000..3ac5979b0 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js @@ -0,0 +1,39 @@ +var tap = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +tap.test("changing root and searching for /b*/**", function (t) { + var glob = require('../') + var path = require('path') + t.test('.', function (t) { + glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, []) + t.end() + }) + }) + + t.test('a', function (t) { + glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ]) + t.end() + }) + }) + + t.test('root=a, cwd=a/b', function (t) { + glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ]) + t.end() + }) + }) + + t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() + }) + + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js new file mode 100644 index 000000000..95c23f99c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js @@ -0,0 +1,46 @@ +var t = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +var glob = require('../') +var path = require('path') + +t.test('.', function (t) { + glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) { + t.ifError(er) + t.like(matches, []) + t.end() + }) +}) + + +t.test('a', function (t) { + console.error("root=" + path.resolve('a')) + glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) { + t.ifError(er) + var wanted = [ + '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' + ].map(function (m) { + return path.join(path.resolve('a'), m).replace(/\\/g, '/') + }) + + t.like(matches, wanted) + t.end() + }) +}) + +t.test('root=a, cwd=a/b', function (t) { + glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) { + return path.join(path.resolve('a'), m).replace(/\\/g, '/') + })) + t.end() + }) +}) + +t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/stat.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/stat.js new file mode 100644 index 000000000..62917114b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/stat.js @@ -0,0 +1,32 @@ +var glob = require('../') +var test = require('tap').test +var path = require('path') + +test('stat all the things', function(t) { + var g = new glob.Glob('a/*abc*/**', { stat: true, cwd: __dirname }) + var matches = [] + g.on('match', function(m) { + matches.push(m) + }) + var stats = [] + g.on('stat', function(m) { + stats.push(m) + }) + g.on('end', function(eof) { + stats = stats.sort() + matches = matches.sort() + eof = eof.sort() + t.same(stats, matches) + t.same(eof, matches) + var cache = Object.keys(this.statCache) + t.same(cache.map(function (f) { + return path.relative(__dirname, f) + }).sort(), matches) + + cache.forEach(function(c) { + t.equal(typeof this.statCache[c], 'object') + }, this) + + t.end() + }) +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js new file mode 100644 index 000000000..e085f0fa7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js @@ -0,0 +1,11 @@ +// remove the fixtures +var tap = require("tap") +, rimraf = require("rimraf") +, path = require("path") + +tap.test("cleanup fixtures", function (t) { + rimraf(path.resolve(__dirname, "a"), function (er) { + t.ifError(er, "removed") + t.end() + }) +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/package.json new file mode 100755 index 000000000..54287e18b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/package.json @@ -0,0 +1,57 @@ +{ + "name": "cli", + "description": "A tool for rapidly building command line apps", + "version": "0.4.5", + "homepage": "http://github.com/chriso/cli", + "keywords": [ + "cli", + "command line", + "opts", + "parseopt", + "opt", + "args", + "console", + "argsparse", + "optparse", + "daemon", + "autocomplete", + "command", + "autocompletion" + ], + "author": { + "name": "Chris O'Hara", + "email": "cohara87@gmail.com" + }, + "main": "cli.js", + "bugs": { + "url": "http://github.com/chriso/cli/issues" + }, + "repository": { + "type": "git", + "url": "http://github.com/chriso/cli.git" + }, + "dependencies": { + "glob": ">= 3.1.4" + }, + "contributors": [ + { + "name": "Douglas Meyer" + } + ], + "engines": { + "node": ">=0.2.5" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "readme": "**cli is a toolkit for rapidly building command line apps - it includes:**\n\n- Full featured opts/args parser\n- Plugin support for adding common options and switches\n- Helper methods for working with input/output and spawning child processes\n- Output colored/styled messages, [progress bars](https://github.com/chriso/cli/blob/master/examples/progress.js) or [spinners](https://github.com/chriso/cli/blob/master/examples/spinner.js)\n- Command [auto-completion](https://github.com/chriso/cli/blob/master/examples/command.js) and [glob support](https://github.com/chriso/cli/blob/master/examples/glob.js)\n\nInstall using `npm install cli` or just bundle [cli.js](https://github.com/chriso/cli/raw/master/cli-min.js) with your app.\n\n## Example apps\n\n### sort.js\n\n```javascript\n#!/usr/bin/env node\nrequire('cli').withStdinLines(function(lines, newline) {\n this.output(lines.sort().join(newline));\n});\n```\n\nTry it out\n\n```bash\n$ ./sort.js < input.txt\n```\n\nLet's add support for an `-n` switch to use a numeric sort, and a `-r` switch to reverse output - only 5 extra lines of code (!)\n\n```javascript\nvar cli = require('cli'), options = cli.parse();\n\ncli.withStdinLines(function(lines, newline) {\n lines.sort(!options.n ? null : function(a, b) {\n return parseInt(a) > parseInt(b);\n });\n if (options.r) lines.reverse();\n this.output(lines.join(newline));\n});\n```\n\n### static.js\n\nLet's create a static file server with daemon support to see the opts parser + plugins in use - note: this requires `npm install creationix daemon`\n\n```javascript\nvar cli = require('cli').enable('daemon', 'status'); //Enable 2 plugins\n\ncli.parse({\n log: ['l', 'Enable logging'],\n port: ['p', 'Listen on this port', 'number', 8080],\n serve: [false, 'Serve static files from PATH', 'path', './public']\n});\n\ncli.main(function(args, options) {\n var server, middleware = [];\n\n if (options.log) {\n this.debug('Enabling logging');\n middleware.push(require('creationix/log')());\n }\n\n this.debug('Serving files from ' + options.serve);\n middleware.push(require('creationix/static')('/', options.serve, 'index.html'));\n\n server = this.createServer(middleware).listen(options.port);\n\n this.ok('Listening on port ' + options.port);\n});\n```\n\nTo output usage information\n\n```bash\n$ ./static.js --help\n```\n\nTo create a daemon that serves files from */tmp*, run\n\n```bash\n$ ./static.js -ld --serve=/tmp\n```\n\nFor more examples, see [./examples](https://github.com/chriso/cli/tree/master/examples)\n\n## Helper methods\n\ncli has methods that collect stdin (newline is autodetected as \\n or \\r\\n)\n\n```javascript\ncli.withStdin(callback); //callback receives stdin as a string\ncli.withStdinLines(callback); //callback receives stdin split into an array of lines (lines, newline)\n```\n\ncli also has a lower level method for working with input line by line (see [./examples/cat.js](https://github.com/chriso/cli/blob/master/examples/cat.js) for an example). \n\n```javascript\ncli.withInput(file, function (line, newline, eof) {\n if (!eof) {\n this.output(line + newline);\n }\n});\n```\n\n*Note: `file` can be omitted if you want to work with stdin*\n\nTo output a progress bar, call\n\n```javascript\ncli.progress(progress); //Where 0 <= progress <= 1\n```\n\nTo spawn a child process, use\n\n```javascript\ncli.exec(cmd, callback); //callback receives the output of the process (split into lines)\n```\n\ncli also comes bundled with kof's [node-natives](https://github.com/kof/node-natives) (access with cli.native) and creationix' [stack](https://github.com/creationix/stack) (access with cli.createServer)\n\n## Plugins\n\nPlugins are a way of adding common opts and can be enabled using \n\n```javascript\ncli.enable(plugin1, [plugin2, ...]); //To disable, use the equivalent disable() method\n```\n\n**help** - *enabled by default*\n\nAdds `-h,--help` to output auto-generated usage information\n\n**version**\n\nAdds `-v,--version` to output version information for the app. cli will attempt to locate and parse a nearby *package.json*\n\nTo set your own app name and version, use `cli.setApp(app_name, version)`\n\n**status**\n\nAdds options to show/hide the stylized status messages that are output to the console when using one of these methods\n\n```javascript\ncli.debug(msg); //Only shown when using --debug\ncli.error(msg);\ncli.fatal(msg); //Exits the process after outputting msg\ncli.info(msg);\ncli.ok(msg);\n```\n\n`-k,--no-color` will omit ANSI color escapes from the output\n\n**glob** - *requires* `npm install glob`\n\nEnables glob matching of arguments\n\n**daemon** - *requires* `npm install daemon`\n\nAdds `-d,--daemon ARG` for daemonizing the process and controlling the resulting daemon\n\n`ARG` can be either start (default), stop, restart, pid (outputs the daemon's pid if it's running), or log (output the daemon's stdout+stderr)\n\n**timeout**\n\nAdds `-t,--timeout N` to exit the process after N seconds with an error\n\n**catchall**\n\nAdds `-c,--catch` to catch and output uncaughtExceptions and resume execution\n\n*Note: Plugins are automatically disabled if an option or switch of the same name is already defined*\n\n## LICENSE\n\n(MIT license)\n\nCopyright (c) 2010 Chris O'Hara \n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "cli@0.4.5", + "dist": { + "shasum": "9e6553090887d5edbbe4fc52f8dba6df3d7a1c93" + }, + "_from": "cli@0.4.x", + "_resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.npmignore new file mode 100644 index 000000000..aa3fd4b85 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.npmignore @@ -0,0 +1,14 @@ +.DS_Store +.monitor +.*.swp +.nodemonignore +releases +*.log +*.err +fleet.json +public/browserify +bin/*.json +.bin +build +compile +.lock-wscript diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.testem.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.testem.json new file mode 100644 index 000000000..633c2ba84 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.testem.json @@ -0,0 +1,14 @@ +{ + "launchers": { + "node": { + "command": "npm test" + } + }, + "src_files": [ + "./**/*.js" + ], + "before_tests": "npm run build", + "on_exit": "rm test/static/bundle.js", + "test_page": "test/static/index.html", + "launch_in_dev": ["node", "phantomjs"] +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.travis.yml b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.travis.yml new file mode 100644 index 000000000..ed178f635 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - 0.9 diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/LICENCE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/LICENCE new file mode 100644 index 000000000..a23e08a85 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/LICENCE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Raynos. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/README.md new file mode 100644 index 000000000..5e480ba5d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/README.md @@ -0,0 +1,32 @@ +# console-browserify + +[![build status][1]][2] + +[![browser support][3]][4] + +Emulate console for all the browsers + +## Example + +```js +var console = require("console-browserify") + +console.log("hello world!") +``` + +## Installation + +`npm install console-browserify` + +## Contributors + + - Raynos + +## MIT Licenced + + + + [1]: https://secure.travis-ci.org/Raynos/console-browserify.png + [2]: http://travis-ci.org/Raynos/console-browserify + [3]: http://ci.testling.com/Raynos/console-browserify.png + [4]: http://ci.testling.com/Raynos/console-browserify diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/index.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/index.js new file mode 100644 index 000000000..bfdf4b358 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/index.js @@ -0,0 +1,85 @@ +/*global window, global*/ +var util = require("util") +var assert = require("assert") + +var slice = Array.prototype.slice +var console +var times = {} + +if (typeof global !== "undefined" && global.console) { + console = global.console +} else if (typeof window !== "undefined" && window.console) { + console = window.console +} else { + console = window.console = {} +} + +var functions = [ + [log, "log"] + , [info, "info"] + , [warn, "warn"] + , [error, "error"] + , [time, "time"] + , [timeEnd, "timeEnd"] + , [trace, "trace"] + , [dir, "dir"] + , [assert, "assert"] +] + +for (var i = 0; i < functions.length; i++) { + var tuple = functions[i] + var f = tuple[0] + var name = tuple[1] + + if (!console[name]) { + console[name] = f + } +} + +module.exports = console + +function log() {} + +function info() { + console.log.apply(console, arguments) +} + +function warn() { + console.log.apply(console, arguments) +} + +function error() { + console.warn.apply(console, arguments) +} + +function time(label) { + times[label] = Date.now() +} + +function timeEnd(label) { + var time = times[label] + if (!time) { + throw new Error("No such label: " + label) + } + + var duration = Date.now() - time + console.log(label + ": " + duration + "ms") +} + +function trace() { + var err = new Error() + err.name = "Trace" + err.message = util.format.apply(null, arguments) + console.error(err.stack) +} + +function dir(object) { + console.log(util.inspect(object) + "\n") +} + +function assert(expression) { + if (!expression) { + var arr = slice.call(arguments, 1) + assert.ok(false, util.format.apply(null, arr)) + } +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/package.json new file mode 100644 index 000000000..b34aba75a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/package.json @@ -0,0 +1,80 @@ +{ + "name": "console-browserify", + "version": "0.1.6", + "description": "Emulate console for all the browsers", + "keywords": [], + "author": { + "name": "Raynos", + "email": "raynos2@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/Raynos/console-browserify.git" + }, + "main": "index", + "homepage": "https://github.com/Raynos/console-browserify", + "contributors": [ + { + "name": "Raynos" + } + ], + "bugs": { + "url": "https://github.com/Raynos/console-browserify/issues", + "email": "raynos2@gmail.com" + }, + "dependencies": {}, + "devDependencies": { + "tape": "~0.2.2", + "browserify": "https://github.com/raynos/node-browserify/tarball/master", + "testem": "~0.2.55", + "jsonify": "0.0.0" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/Raynos/console-browserify/raw/master/LICENSE" + } + ], + "scripts": { + "test": "node ./test", + "build": "browserify test/index.js -o test/static/bundle.js", + "testem": "testem" + }, + "testling": { + "files": "test/index.js", + "browsers": { + "ie": [ + "6", + "7", + "8", + "9", + "10" + ], + "firefox": [ + "16", + "17", + "nightly" + ], + "chrome": [ + "22", + "23", + "canary" + ], + "opera": [ + "12", + "next" + ], + "safari": [ + "5.1" + ] + } + }, + "readme": "# console-browserify\n\n[![build status][1]][2]\n\n[![browser support][3]][4]\n\nEmulate console for all the browsers\n\n## Example\n\n```js\nvar console = require(\"console-browserify\")\n\nconsole.log(\"hello world!\")\n```\n\n## Installation\n\n`npm install console-browserify`\n\n## Contributors\n\n - Raynos\n\n## MIT Licenced\n\n\n\n [1]: https://secure.travis-ci.org/Raynos/console-browserify.png\n [2]: http://travis-ci.org/Raynos/console-browserify\n [3]: http://ci.testling.com/Raynos/console-browserify.png\n [4]: http://ci.testling.com/Raynos/console-browserify\n", + "readmeFilename": "README.md", + "_id": "console-browserify@0.1.6", + "dist": { + "shasum": "3a1463b25cac6013ddc0e06678420a9dfdb9677a" + }, + "_from": "console-browserify@0.1.x", + "_resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/index.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/index.js new file mode 100644 index 000000000..26dfaad6e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/index.js @@ -0,0 +1,67 @@ +var console = require("../index") +var test = require("tape") + +if (typeof window !== "undefined" && !window.JSON) { + window.JSON = require("jsonify") +} + +test("console has expected methods", function (assert) { + assert.ok(console.log) + assert.ok(console.info) + assert.ok(console.warn) + assert.ok(console.dir) + assert.ok(console.time, "time") + assert.ok(console.timeEnd, "timeEnd") + assert.ok(console.trace, "trace") + assert.ok(console.assert) + + assert.end() +}) + +test("invoke console.log", function (assert) { + console.log("test-log") + + assert.end() +}) + +test("invoke console.info", function (assert) { + console.info("test-info") + + assert.end() +}) + +test("invoke console.warn", function (assert) { + console.warn("test-warn") + + assert.end() +}) + +test("invoke console.time", function (assert) { + console.time("label") + + assert.end() +}) + +test("invoke console.trace", function (assert) { + console.trace("test-trace") + + assert.end() +}) + +test("invoke console.assert", function (assert) { + console.assert(true) + + assert.end() +}) + +test("invoke console.dir", function (assert) { + console.dir("test-dir") + + assert.end() +}) + +test("invoke console.timeEnd", function (assert) { + console.timeEnd("label") + + assert.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/index.html b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/index.html new file mode 100644 index 000000000..dd55012f0 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/index.html @@ -0,0 +1,12 @@ + + + + + TAPE Example + + + + + + + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/test-adapter.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/test-adapter.js new file mode 100644 index 000000000..8b4c12dc5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/console-browserify/test/static/test-adapter.js @@ -0,0 +1,53 @@ +(function () { + var Testem = window.Testem + var regex = /^((?:not )?ok) (\d+) (.+)$/ + + Testem.useCustomAdapter(tapAdapter) + + function tapAdapter(socket){ + var results = { + failed: 0 + , passed: 0 + , total: 0 + , tests: [] + } + + socket.emit('tests-start') + + Testem.handleConsoleMessage = function(msg){ + var m = msg.match(regex) + if (m) { + var passed = m[1] === 'ok' + var test = { + passed: passed ? 1 : 0, + failed: passed ? 0 : 1, + total: 1, + id: m[2], + name: m[3], + items: [] + } + + if (passed) { + results.passed++ + } else { + console.error("failure", m) + + results.failed++ + } + + results.total++ + + // console.log("emitted test", test) + socket.emit('test-result', test) + results.tests.push(test) + } else if (msg === '# ok' || msg.match(/^# tests \d+/)){ + // console.log("emitted all test") + socket.emit('all-test-results', results) + } + + // return false if you want to prevent the console message from + // going to the console + // return false + } + } +}()) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/README.md new file mode 100644 index 000000000..6fd07d2e9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/README.md @@ -0,0 +1,218 @@ +# minimatch + +A minimal matching utility. + +[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch) + + +This is the matching library used internally by npm. + +Eventually, it will replace the C binding in node-glob. + +It works by converting glob expressions into JavaScript `RegExp` +objects. + +## Usage + +```javascript +var minimatch = require("minimatch") + +minimatch("bar.foo", "*.foo") // true! +minimatch("bar.foo", "*.bar") // false! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +### Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between minimatch and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. **Note that this is different from the way that `**` is +handled by ruby's `Dir` class.** + +If an escaped pattern has no matches, and the `nonull` flag is set, +then minimatch.match returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + + +## Minimatch Class + +Create a minimatch object by instanting the `minimatch.Minimatch` class. + +```javascript +var Minimatch = require("minimatch").Minimatch +var mm = new Minimatch(pattern, options) +``` + +### Properties + +* `pattern` The original pattern the minimatch object represents. +* `options` The options supplied to the constructor. +* `set` A 2-dimensional array of regexp or string expressions. + Each row in the + array corresponds to a brace-expanded pattern. Each item in the row + corresponds to a single path-part. For example, the pattern + `{a,b/c}/d` would expand to a set of patterns like: + + [ [ a, d ] + , [ b, c, d ] ] + + If a portion of the pattern doesn't have any "magic" in it + (that is, it's something like `"foo"` rather than `fo*o?`), then it + will be left as a string rather than converted to a regular + expression. + +* `regexp` Created by the `makeRe` method. A single regular expression + expressing the entire pattern. This is useful in cases where you wish + to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. +* `negate` True if the pattern is negated. +* `comment` True if the pattern is a comment. +* `empty` True if the pattern is `""`. + +### Methods + +* `makeRe` Generate the `regexp` member if necessary, and return it. + Will return `false` if the pattern is invalid. +* `match(fname)` Return true if the filename matches the pattern, or + false otherwise. +* `matchOne(fileArray, patternArray, partial)` Take a `/`-split + filename, and match it against a single row in the `regExpSet`. This + method is mainly for internal use, but is exposed so that it can be + used by a glob-walker that needs to avoid excessive filesystem calls. + +All other methods are internal, and will be called as necessary. + +## Functions + +The top-level exported function has a `cache` property, which is an LRU +cache set to store 100 items. So, calling these methods repeatedly +with the same pattern and options will use the same Minimatch object, +saving the cost of parsing it multiple times. + +### minimatch(path, pattern, options) + +Main export. Tests a path against the pattern using the options. + +```javascript +var isJS = minimatch(file, "*.js", { matchBase: true }) +``` + +### minimatch.filter(pattern, options) + +Returns a function that tests its +supplied argument, suitable for use with `Array.filter`. Example: + +```javascript +var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) +``` + +### minimatch.match(list, pattern, options) + +Match against the list of +files, in the style of fnmatch or glob. If nothing is matched, and +options.nonull is set, then return a list containing the pattern itself. + +```javascript +var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) +``` + +### minimatch.makeRe(pattern, options) + +Make a regular expression object from the pattern. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### nobrace + +Do not expand `{a,b}` and `{1..3}` brace sets. + +### noglobstar + +Disable `**` matching against multiple folder names. + +### dot + +Allow patterns to match filenames starting with a period, even if +the pattern does not explicitly have a period in that spot. + +Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` +is set. + +### noext + +Disable "extglob" style patterns like `+(a|b)`. + +### nocase + +Perform a case-insensitive match. + +### nonull + +When a match is not found by `minimatch.match`, return a list containing +the pattern itself. When set, an empty list is returned if there are +no matches. + +### matchBase + +If set, then patterns without slashes will be matched +against the basename of the path if it contains slashes. For example, +`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + +### nocomment + +Suppress the behavior of treating `#` at the start of a pattern as a +comment. + +### nonegate + +Suppress the behavior of treating a leading `!` character as negation. + +### flipNegate + +Returns from negate expressions the same as if they were not negated. +(Ie, true on a hit, false on a miss.) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/minimatch.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/minimatch.js new file mode 100644 index 000000000..405746b67 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/minimatch.js @@ -0,0 +1,1079 @@ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.monkeyPatch = monkeyPatch +function monkeyPatch () { + var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") + var orig = desc.value + desc.value = function (p) { + if (p instanceof Minimatch) return p.match(this) + return orig.call(this, p) + } + Object.defineProperty(String.prototype, desc) +} + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) console.error(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + if (options.debug) console.error(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + if (options.debug) console.error(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + if (options.debug) console.error(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + // console.error(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + // console.error("no sets") + return [pattern] + } + + var tail = braceExpand(pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + // console.error("numset", numset[1], numset[2]) + var suf = braceExpand(pattern.substr(numset[0].length), options) + , start = +numset[1] + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + for (var i = start; i != (end + inc); i += inc) { + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(i + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + // console.error("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + // console.error("didn't close", pattern) + return braceExpand("\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + // console.error("set", set) + // console.error("suffix", pattern.substr(i)) + var suf = braceExpand(pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + // console.error("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand(p, options) + }) + // console.error("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + if (options.debug) { + console.error("%s\t%s %s %j", pattern, i, re, c) + } + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + if (options.debug) { + console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + } + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + // console.error("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + // console.error("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + if (options.debug) { + console.error(this.pattern, "split", f) + } + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + // console.error(this.pattern, "set", set) + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i] + var hit = this.matchOne(f, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + if (options.debug) { + console.error("matchOne", + { "this": this + , file: file + , pattern: pattern }) + } + + if (options.matchBase && pattern.length === 1) { + file = path.basename(file.join("/")).split("/") + } + + if (options.debug) { + console.error("matchOne", file.length, pattern.length) + } + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + if (options.debug) { + console.error("matchOne loop") + } + var p = pattern[pi] + , f = file[fi] + + if (options.debug) { + console.error(pattern, p, f) + } + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + if (options.debug) + console.error('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + if (options.debug) + console.error('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + if (options.debug) { + console.error('\nglobstar while', + file, fr, pattern, pr, swallowee) + } + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + if (options.debug) + console.error('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + if (options.debug) + console.error("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + if (options.debug) + console.error('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + // console.error("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + if (options.debug) { + console.error("string match", p, f, hit) + } + } else { + hit = f.match(p) + if (options.debug) { + console.error("pattern match", p, f, hit) + } + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 000000000..07e6e472c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/AUTHORS b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/AUTHORS new file mode 100644 index 000000000..016d7fbe1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 000000000..03ee0f985 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,97 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/bench.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/bench.js new file mode 100644 index 000000000..91115400b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/bench.js @@ -0,0 +1,25 @@ +var LRU = require('lru-cache'); + +var max = +process.argv[2] || 10240; +var more = 102400; + +var cache = LRU({ + max: max, maxAge: 86400e3 +}); + +// fill cache +for (var i = 0; i < max; ++i) { + cache.set(i, {}); +} + +var start = process.hrtime(); + +// adding more items +for ( ; i < max+more; ++i) { + cache.set(i, {}); +} + +var end = process.hrtime(start); +var msecs = end[0] * 1E3 + end[1] / 1E6; + +console.log('adding %d items took %d ms', more, msecs.toPrecision(5)); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 000000000..49c1dc6de --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,263 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) { + return new LRUCache(options) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + + if (!options) options = {} + + max = options.max + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var allowStale = options.stale || false + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , lru = 0 // least recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + i++ + var hit = lruList[k] + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } + } + + this.keys = function () { + var keys = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + keys[i++] = hit.key + } + return keys + } + + this.values = function () { + var values = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + values[i++] = hit.value + } + return values + } + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.dumpLru = function () { + return lruList + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.has = function (key) { + if (!hOP(cache, key)) return false + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + return false + } + return true + } + + this.get = function (key) { + return get(key, true) + } + + this.peek = function (key) { + return get(key, false) + } + + function get (key, doUse) { + var hit = cache[key] + if (hit) { + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } else { + if (doUse) use(hit) + } + if (hit) hit = hit.value + } + return hit + } + + function use (hit) { + shiftLU(hit) + hit.lu = mru ++ + lruList[hit.lu] = hit + } + + this.del = function (key) { + del(cache[key]) + } + + function trim () { + while (lru < mru && length > max) + del(lruList[lru]) + } + + function shiftLU(hit) { + delete lruList[ hit.lu ] + while (lru < mru && !lruList[lru]) lru ++ + } + + function del(hit) { + if (hit) { + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + itemCount -- + delete cache[ hit.key ] + shiftLU(hit) + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 000000000..411acad3b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,62 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.3.1", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `peek(key)`\n\n Returns the key value (or `undefined` if not found) without\n updating the \"recently used\"-ness of the key.\n\n (If you find yourself using this a lot, you *might* be using the\n wrong sort of data structure, but there are some use cases where\n it's handy.)\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "_id": "lru-cache@2.3.1", + "_from": "lru-cache@2" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 000000000..70f3f8beb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,329 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/foreach.js new file mode 100644 index 000000000..eefb80d9d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 000000000..7af45b022 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 000000000..7e365129e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/README.md @@ -0,0 +1,53 @@ +# sigmund + +Quick and dirty signatures for Objects. + +This is like a much faster `deepEquals` comparison, which returns a +string key suitable for caches and the like. + +## Usage + +```javascript +function doSomething (someObj) { + var key = sigmund(someObj, maxDepth) // max depth defaults to 10 + var cached = cache.get(key) + if (cached) return cached) + + var result = expensiveCalculation(someObj) + cache.set(key, result) + return result +} +``` + +The resulting key will be as unique and reproducible as calling +`JSON.stringify` or `util.inspect` on the object, but is much faster. +In order to achieve this speed, some differences are glossed over. +For example, the object `{0:'foo'}` will be treated identically to the +array `['foo']`. + +Also, just as there is no way to summon the soul from the scribblings +of a cocain-addled psychoanalyst, there is no way to revive the object +from the signature string that sigmund gives you. In fact, it's +barely even readable. + +As with `sys.inspect` and `JSON.stringify`, larger objects will +produce larger signature strings. + +Because sigmund is a bit less strict than the more thorough +alternatives, the strings will be shorter, and also there is a +slightly higher chance for collisions. For example, these objects +have the same signature: + + var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} + var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +Like a good Freudian, sigmund is most effective when you already have +some understanding of what you're looking for. It can help you help +yourself, but you must be willing to do some work as well. + +Cycles are handled, and cyclical objects are silently omitted (though +the key is included in the signature output.) + +The second argument is the maximum depth, which defaults to 10, +because that is the maximum object traversal depth covered by most +insurance carriers. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 000000000..5acfd6d90 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/bench.js @@ -0,0 +1,283 @@ +// different ways to id objects +// use a req/res pair, since it's crazy deep and cyclical + +// sparseFE10 and sigmund are usually pretty close, which is to be expected, +// since they are essentially the same algorithm, except that sigmund handles +// regular expression objects properly. + + +var http = require('http') +var util = require('util') +var sigmund = require('./sigmund.js') +var sreq, sres, creq, cres, test + +http.createServer(function (q, s) { + sreq = q + sres = s + sres.end('ok') + this.close(function () { setTimeout(function () { + start() + }, 200) }) +}).listen(1337, function () { + creq = http.get({ port: 1337 }) + creq.on('response', function (s) { cres = s }) +}) + +function start () { + test = [sreq, sres, creq, cres] + // test = sreq + // sreq.sres = sres + // sreq.creq = creq + // sreq.cres = cres + + for (var i in exports.compare) { + console.log(i) + var hash = exports.compare[i]() + console.log(hash) + console.log(hash.length) + console.log('') + } + + require('bench').runMain() +} + +function customWs (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '') + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return customWs(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + customWs(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function custom (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return '' + obj + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return custom(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + custom(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function sparseFE2 (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ':' + ch(v[k], depth + 1) + }) + soFar += '}' + } + ch(obj, 0) + return soFar +} + +function sparseFE (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ch(v[k], depth + 1) + }) + } + ch(obj, 0) + return soFar +} + +function sparse (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ch(v[k], depth + 1) + } + } + ch(obj, 0) + return soFar +} + +function noCommas (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + + +function flatten (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + soFar += ',' + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + +exports.compare = +{ + // 'custom 2': function () { + // return custom(test, 2, 0) + // }, + // 'customWs 2': function () { + // return customWs(test, 2, 0) + // }, + 'JSON.stringify (guarded)': function () { + var seen = [] + return JSON.stringify(test, function (k, v) { + if (typeof v !== 'object' || !v) return v + if (seen.indexOf(v) !== -1) return undefined + seen.push(v) + return v + }) + }, + + 'flatten 10': function () { + return flatten(test, 10) + }, + + // 'flattenFE 10': function () { + // return flattenFE(test, 10) + // }, + + 'noCommas 10': function () { + return noCommas(test, 10) + }, + + 'sparse 10': function () { + return sparse(test, 10) + }, + + 'sparseFE 10': function () { + return sparseFE(test, 10) + }, + + 'sparseFE2 10': function () { + return sparseFE2(test, 10) + }, + + sigmund: function() { + return sigmund(test, 10) + }, + + + // 'util.inspect 1': function () { + // return util.inspect(test, false, 1, false) + // }, + // 'util.inspect undefined': function () { + // util.inspect(test) + // }, + // 'util.inspect 2': function () { + // util.inspect(test, false, 2, false) + // }, + // 'util.inspect 3': function () { + // util.inspect(test, false, 3, false) + // }, + // 'util.inspect 4': function () { + // util.inspect(test, false, 4, false) + // }, + // 'util.inspect Infinity': function () { + // util.inspect(test, false, Infinity, false) + // } +} + +/** results +**/ diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 000000000..ec8e2eb3e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,41 @@ +{ + "name": "sigmund", + "version": "1.0.0", + "description": "Quick and dirty signatures for Objects.", + "main": "sigmund.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.0" + }, + "scripts": { + "test": "tap test/*.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/sigmund" + }, + "keywords": [ + "object", + "signature", + "key", + "data", + "psychoanalysis" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "BSD", + "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/sigmund/issues" + }, + "_id": "sigmund@1.0.0", + "_from": "sigmund@~1.0.0" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 000000000..82c7ab8ce --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -0,0 +1,39 @@ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 000000000..50c53a13e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -0,0 +1,24 @@ +var test = require('tap').test +var sigmund = require('../sigmund.js') + + +// occasionally there are duplicates +// that's an acceptable edge-case. JSON.stringify and util.inspect +// have some collision potential as well, though less, and collision +// detection is expensive. +var hash = '{abc/def/g{0h1i2{jkl' +var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} +var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +var obj3 = JSON.parse(JSON.stringify(obj1)) +obj3.c = /def/ +obj3.g[2].cycle = obj3 +var cycleHash = '{abc/def/g{0h1i2{jklcycle' + +test('basic', function (t) { + t.equal(sigmund(obj1), hash) + t.equal(sigmund(obj2), hash) + t.equal(sigmund(obj3), cycleHash) + t.end() +}) + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/package.json new file mode 100644 index 000000000..d5a1fd001 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.2.12", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE" + }, + "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n### Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n Each row in the\n array corresponds to a brace-expanded pattern. Each item in the row\n corresponds to a single path-part. For example, the pattern\n `{a,b/c}/d` would expand to a set of patterns like:\n\n [ [ a, d ]\n , [ b, c, d ] ]\n\n If a portion of the pattern doesn't have any \"magic\" in it\n (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n will be left as a string rather than converted to a regular\n expression.\n\n* `regexp` Created by the `makeRe` method. A single regular expression\n expressing the entire pattern. This is useful in cases where you wish\n to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n filename, and match it against a single row in the `regExpSet`. This\n method is mainly for internal use, but is exposed so that it can be\n used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items. So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`. Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob. If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself. When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes. For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/minimatch/issues" + }, + "_id": "minimatch@0.2.12", + "_from": "minimatch@0.x.x" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/basic.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/basic.js new file mode 100644 index 000000000..ae7ac73c7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/basic.js @@ -0,0 +1,399 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + + +var patterns = + [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + // https://github.com/isaacs/minimatch/issues/5 + , function () { + files = [ 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' + , 'a/b/.x' + , 'a/b/.x/' + , 'a/.x/b' + , '.x' + , '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b/.x/c' + , '.x/.x' ] + } + , ["**/.x/**", [ '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b' + , 'a/b/.x/' + , 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' ] ] + + ] + +var regexps = + [ '/^(?:(?=.)a[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:\\*)$/', + '/^(?:(?=.)\\*[^/]*?)$/', + '/^(?:\\*\\*)$/', + '/^(?:(?=.)b[^/]*?\\/)$/', + '/^(?:(?=.)c[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/', + '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/', + '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/', + '/^(?:(?=.)a[^/]*?[^c])$/', + '/^(?:(?=.)a[X-]b)$/', + '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/', + '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[^/]c)$/', + '/^(?:a\\*c)$/', + 'false', + '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/', + '/^(?:man\\/man1\\/bash\\.1)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[-abc])$/', + '/^(?:(?!\\.)(?=.)[abc-])$/', + '/^(?:\\\\)$/', + '/^(?:(?!\\.)(?=.)[\\\\])$/', + '/^(?:(?!\\.)(?=.)[\\[])$/', + '/^(?:\\[)$/', + '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[\\]])$/', + '/^(?:(?!\\.)(?=.)[\\]-])$/', + '/^(?:(?!\\.)(?=.)[a-z])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:\\[\\])$/', + '/^(?:\\[abc)$/', + '/^(?:(?=.)XYZ)$/i', + '/^(?:(?=.)ab[^/]*?)$/i', + '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i', + '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/', + '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/', + '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/', + '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/', + '/^(?:(?=.)a[^/]b)$/', + '/^(?:(?=.)#[^/]*?)$/', + '/^(?!^(?:(?=.)a[^/]*?)$).*$/', + '/^(?:(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)a[^/]*?)$/', + '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ] +var re = 0; + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + patterns.forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var m = new mm.Minimatch(pattern, options) + var r = m.makeRe() + var expectRe = regexps[re++] + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + + t.equal(tapOpts.re, expectRe, tapOpts) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/brace-expand.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/brace-expand.js new file mode 100644 index 000000000..7ee278a27 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/caching.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/caching.js new file mode 100644 index 000000000..0fec4b0fa --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/defaults.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/defaults.js new file mode 100644 index 000000000..25f1f601c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.documentup.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.documentup.json new file mode 100644 index 000000000..57fe30116 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.documentup.json @@ -0,0 +1,6 @@ +{ + "name": "ShellJS", + "twitter": [ + "r2r" + ] +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.npmignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.travis.yml b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.travis.yml new file mode 100644 index 000000000..5caf59981 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/LICENSE new file mode 100644 index 000000000..1b35ee9fb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2012, Artur Adib +All rights reserved. + +You may use this project under the terms of the New BSD license as follows: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Artur Adib nor the + names of the contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 ARTUR ADIB 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. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/README.md new file mode 100644 index 000000000..8b4559293 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/README.md @@ -0,0 +1,513 @@ +# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs) + +ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts! + +The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and battled-tested in projects like: + ++ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader ++ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger ++ [JSHint](http://jshint.com) - Most popular JavaScript linter ++ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers ++ [Yeoman](http://yeoman.io/) - Web application stack and development tool ++ [Deployd.com](http://deployd.com) - Open source PaaS for quick API backend generation + +and [many more](https://npmjs.org/browse/depended/shelljs). + +## Installing + +Via npm: + +```bash +$ npm install [-g] shelljs +``` + +If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to +run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder: + +```bash +$ shjs my_script +``` + +You can also just copy `shell.js` into your project's directory, and `require()` accordingly. + + +## Examples + +### JavaScript + +```javascript +require('shelljs/global'); + +if (!which('git')) { + echo('Sorry, this script requires git'); + exit(1); +} + +// Copy files to release dir +mkdir('-p', 'out/Release'); +cp('-R', 'stuff/*', 'out/Release'); + +// Replace macros in each .js file +cd('lib'); +ls('*.js').forEach(function(file) { + sed('-i', 'BUILD_VERSION', 'v0.1.2', file); + sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file); + sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file); +}); +cd('..'); + +// Run external tool synchronously +if (exec('git commit -am "Auto-commit"').code !== 0) { + echo('Error: Git commit failed'); + exit(1); +} +``` + +### CoffeeScript + +```coffeescript +require 'shelljs/global' + +if not which 'git' + echo 'Sorry, this script requires git' + exit 1 + +# Copy files to release dir +mkdir '-p', 'out/Release' +cp '-R', 'stuff/*', 'out/Release' + +# Replace macros in each .js file +cd 'lib' +for file in ls '*.js' + sed '-i', 'BUILD_VERSION', 'v0.1.2', file + sed '-i', /.*REMOVE_THIS_LINE.*\n/, '', file + sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat 'macro.js', file +cd '..' + +# Run external tool synchronously +if (exec 'git commit -am "Auto-commit"').code != 0 + echo 'Error: Git commit failed' + exit 1 +``` + +## Global vs. Local + +The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`. + +Example: + +```javascript +var shell = require('shelljs'); +shell.echo('hello world'); +``` + +## Make tool + +A convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script. + +Example (CoffeeScript): + +```coffeescript +require 'shelljs/make' + +target.all = -> + target.bundle() + target.docs() + +target.bundle = -> + cd __dirname + mkdir 'build' + cd 'lib' + (cat '*.js').to '../build/output.js' + +target.docs = -> + cd __dirname + mkdir 'docs' + cd 'lib' + for file in ls '*.js' + text = grep '//@', file # extract special comments + text.replace '//@', '' # remove comment tags + text.to 'docs/my_docs.md' +``` + +To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on. + + + + + + +## Command reference + + +All commands run synchronously, unless otherwise stated. + + +### cd('dir') +Changes to directory `dir` for the duration of the script + +### pwd() +Returns the current directory. + +### ls([options ,] path [,path ...]) +### ls([options ,] path_array) +Available options: + ++ `-R`: recursive ++ `-A`: all files (include files beginning with `.`, except for `.` and `..`) + +Examples: + +```javascript +ls('projs/*.js'); +ls('-R', '/users/me', '/tmp'); +ls('-R', ['/users/me', '/tmp']); // same as above +``` + +Returns array of files in the given path, or in current directory if no path provided. + +### find(path [,path ...]) +### find(path_array) +Examples: + +```javascript +find('src', 'lib'); +find(['src', 'lib']); // same as above +find('.').filter(function(file) { return file.match(/\.js$/); }); +``` + +Returns array of all files (however deep) in the given paths. + +The main difference from `ls('-R', path)` is that the resulting file names +include the base directories, e.g. `lib/resources/file1` instead of just `file1`. + +### cp([options ,] source [,source ...], dest) +### cp([options ,] source_array, dest) +Available options: + ++ `-f`: force ++ `-r, -R`: recursive + +Examples: + +```javascript +cp('file1', 'dir1'); +cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); +cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above +``` + +Copies files. The wildcard `*` is accepted. + +### rm([options ,] file [, file ...]) +### rm([options ,] file_array) +Available options: + ++ `-f`: force ++ `-r, -R`: recursive + +Examples: + +```javascript +rm('-rf', '/tmp/*'); +rm('some_file.txt', 'another_file.txt'); +rm(['some_file.txt', 'another_file.txt']); // same as above +``` + +Removes files. The wildcard `*` is accepted. + +### mv(source [, source ...], dest') +### mv(source_array, dest') +Available options: + ++ `f`: force + +Examples: + +```javascript +mv('-f', 'file', 'dir/'); +mv('file1', 'file2', 'dir/'); +mv(['file1', 'file2'], 'dir/'); // same as above +``` + +Moves files. The wildcard `*` is accepted. + +### mkdir([options ,] dir [, dir ...]) +### mkdir([options ,] dir_array) +Available options: + ++ `p`: full path (will create intermediate dirs if necessary) + +Examples: + +```javascript +mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); +mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above +``` + +Creates directories. + +### test(expression) +Available expression primaries: + ++ `'-b', 'path'`: true if path is a block device ++ `'-c', 'path'`: true if path is a character device ++ `'-d', 'path'`: true if path is a directory ++ `'-e', 'path'`: true if path exists ++ `'-f', 'path'`: true if path is a regular file ++ `'-L', 'path'`: true if path is a symboilc link ++ `'-p', 'path'`: true if path is a pipe (FIFO) ++ `'-S', 'path'`: true if path is a socket + +Examples: + +```javascript +if (test('-d', path)) { /* do something with dir */ }; +if (!test('-f', path)) continue; // skip if it's a regular file +``` + +Evaluates expression using the available primaries and returns corresponding value. + +### cat(file [, file ...]) +### cat(file_array) + +Examples: + +```javascript +var str = cat('file*.txt'); +var str = cat('file1', 'file2'); +var str = cat(['file1', 'file2']); // same as above +``` + +Returns a string containing the given file, or a concatenated string +containing the files if more than one file is given (a new line character is +introduced between each file). Wildcard `*` accepted. + +### 'string'.to(file) + +Examples: + +```javascript +cat('input.txt').to('output.txt'); +``` + +Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as +those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ + +### sed([options ,] search_regex, replace_str, file) +Available options: + ++ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ + +Examples: + +```javascript +sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); +sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); +``` + +Reads an input string from `file` and performs a JavaScript `replace()` on the input +using the given search regex and replacement string. Returns the new string after replacement. + +### grep([options ,] regex_filter, file [, file ...]) +### grep([options ,] regex_filter, file_array) +Available options: + ++ `-v`: Inverse the sense of the regex and print the lines not matching the criteria. + +Examples: + +```javascript +grep('-v', 'GLOBAL_VARIABLE', '*.js'); +grep('GLOBAL_VARIABLE', '*.js'); +``` + +Reads input string from given files and returns a string containing all lines of the +file that match the given `regex_filter`. Wildcard `*` accepted. + +### which(command) + +Examples: + +```javascript +var nodeExec = which('node'); +``` + +Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. +Returns string containing the absolute path to the command. + +### echo(string [,string ...]) + +Examples: + +```javascript +echo('hello world'); +var str = echo('hello world'); +``` + +Prints string to stdout, and returns string with additional utility methods +like `.to()`. + +### dirs([options | '+N' | '-N']) + +Available options: + ++ `-c`: Clears the directory stack by deleting all of the elements. + +Arguments: + ++ `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero. ++ `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero. + +Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified. + +See also: pushd, popd + +### pushd([options,] [dir | '-N' | '+N']) + +Available options: + ++ `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated. + +Arguments: + ++ `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`. ++ `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. ++ `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. + +Examples: + +```javascript +// process.cwd() === '/usr' +pushd('/etc'); // Returns /etc /usr +pushd('+1'); // Returns /usr /etc +``` + +Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack. + +### popd([options,] ['-N' | '+N']) + +Available options: + ++ `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated. + +Arguments: + ++ `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero. ++ `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero. + +Examples: + +```javascript +echo(process.cwd()); // '/usr' +pushd('/etc'); // '/etc /usr' +echo(process.cwd()); // '/etc' +popd(); // '/usr' +echo(process.cwd()); // '/usr' +``` + +When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack. + +### exit(code) +Exits the current process with the given exit code. + +### env['VAR_NAME'] +Object containing environment variables (both getter and setter). Shortcut to process.env. + +### exec(command [, options] [, callback]) +Available options (all `false` by default): + ++ `async`: Asynchronous execution. Defaults to true if a callback is provided. ++ `silent`: Do not echo program output to console. + +Examples: + +```javascript +var version = exec('node --version', {silent:true}).output; + +var child = exec('some_long_running_process', {async:true}); +child.stdout.on('data', function(data) { + /* ... do something with data ... */ +}); + +exec('some_long_running_process', function(code, output) { + console.log('Exit code:', code); + console.log('Program output:', output); +}); +``` + +Executes the given `command` _synchronously_, unless otherwise specified. +When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's +`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and +the `callback` gets the arguments `(code, output)`. + +**Note:** For long-lived processes, it's best to run `exec()` asynchronously as +the current synchronous implementation uses a lot of CPU. This should be getting +fixed soon. + +### chmod(octal_mode || octal_string, file) +### chmod(symbolic_mode, file) + +Available options: + ++ `-v`: output a diagnostic for every file processed ++ `-c`: like verbose but report only when a change is made ++ `-R`: change files and directories recursively + +Examples: + +```javascript +chmod(755, '/Users/brandon'); +chmod('755', '/Users/brandon'); // same as above +chmod('u+x', '/Users/brandon'); +``` + +Alters the permissions of a file or directory by either specifying the +absolute permissions in octal form or expressing the changes in symbols. +This command tries to mimic the POSIX behavior as much as possible. +Notable exceptions: + ++ In symbolic modes, 'a-r' and '-r' are identical. No consideration is + given to the umask. ++ There is no "quiet" option since default behavior is to run silent. + +## Configuration + + +### config.silent +Example: + +```javascript +var silentState = config.silent; // save old silent state +config.silent = true; +/* ... */ +config.silent = silentState; // restore old silent state +``` + +Suppresses all command output if `true`, except for `echo()` calls. +Default is `false`. + +### config.fatal +Example: + +```javascript +config.fatal = true; +cp('this_file_does_not_exist', '/dev/null'); // dies here +/* more commands... */ +``` + +If `true` the script will die on errors. Default is `false`. + +## Non-Unix commands + + +### tempdir() +Searches and returns string containing a writeable, platform-dependent temporary directory. +Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). + +### error() +Tests if error occurred in the last command. Returns `null` if no error occurred, +otherwise returns string explaining the error diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/bin/shjs b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/bin/shjs new file mode 100755 index 000000000..d239a7ad4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/bin/shjs @@ -0,0 +1,51 @@ +#!/usr/bin/env node +require('../global'); + +if (process.argv.length < 3) { + console.log('ShellJS: missing argument (script name)'); + console.log(); + process.exit(1); +} + +var args, + scriptName = process.argv[2]; +env['NODE_PATH'] = __dirname + '/../..'; + +if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { + if (test('-f', scriptName + '.js')) + scriptName += '.js'; + if (test('-f', scriptName + '.coffee')) + scriptName += '.coffee'; +} + +if (!test('-f', scriptName)) { + console.log('ShellJS: script not found ('+scriptName+')'); + console.log(); + process.exit(1); +} + +args = process.argv.slice(3); + +for (var i = 0, l = args.length; i < l; i++) { + if (args[i][0] !== "-"){ + args[i] = '"' + args[i] + '"'; // fixes arguments with multiple words + } +} + +if (scriptName.match(/\.coffee$/)) { + // + // CoffeeScript + // + if (which('coffee')) { + exec('coffee ' + scriptName + ' ' + args.join(' '), { async: true }); + } else { + console.log('ShellJS: CoffeeScript interpreter not found'); + console.log(); + process.exit(1); + } +} else { + // + // JavaScript + // + exec('node ' + scriptName + ' ' + args.join(' '), { async: true }); +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/global.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/global.js new file mode 100644 index 000000000..97f0033cc --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/global.js @@ -0,0 +1,3 @@ +var shell = require('./shell.js'); +for (var cmd in shell) + global[cmd] = shell[cmd]; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/jshint.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/jshint.json new file mode 100644 index 000000000..205ed9c27 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/jshint.json @@ -0,0 +1,4 @@ +{ + "loopfunc": true, + "sub": true +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/make.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/make.js new file mode 100644 index 000000000..b636447e5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/make.js @@ -0,0 +1,48 @@ +require('./global'); +config.fatal = true; + +global.target = {}; + +// This ensures we only execute the script targets after the entire script has +// been evaluated +var args = process.argv.slice(2); +setTimeout(function() { + var t; + + if (args.length === 1 && args[0] === '--help') { + console.log('Available targets:'); + for (t in target) + console.log(' ' + t); + return; + } + + // Wrap targets to prevent duplicate execution + for (t in target) { + (function(t, oldTarget){ + + // Wrap it + target[t] = function(force) { + if (oldTarget.done && !force) + return; + oldTarget.done = true; + return oldTarget.apply(oldTarget, arguments); + }; + + })(t, target[t]); + } + + // Execute desired targets + if (args.length > 0) { + args.forEach(function(arg) { + if (arg in target) + target[arg](); + else { + console.log('no such target: ' + arg); + exit(1); + } + }); + } else if ('all' in target) { + target.all(); + } + +}, 0); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/package.json new file mode 100644 index 000000000..3d365f0d7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/package.json @@ -0,0 +1,48 @@ +{ + "name": "shelljs", + "version": "0.1.4", + "author": { + "name": "Artur Adib", + "email": "aadib@mozilla.com" + }, + "description": "Portable Unix shell commands for Node.js", + "keywords": [ + "unix", + "shell", + "makefile", + "make", + "jake", + "synchronous" + ], + "repository": { + "type": "git", + "url": "git://github.com/arturadib/shelljs.git" + }, + "homepage": "http://github.com/arturadib/shelljs", + "main": "./shell.js", + "scripts": { + "test": "node scripts/run-tests" + }, + "bin": { + "shjs": "./bin/shjs" + }, + "dependencies": {}, + "devDependencies": { + "jshint": "~1.1.0" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# ShellJS - Unix shell commands for Node.js [![Build Status](https://secure.travis-ci.org/arturadib/shelljs.png)](http://travis-ci.org/arturadib/shelljs)\n\nShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts!\n\nThe project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and battled-tested in projects like:\n\n+ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader\n+ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger\n+ [JSHint](http://jshint.com) - Most popular JavaScript linter\n+ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers\n+ [Yeoman](http://yeoman.io/) - Web application stack and development tool\n+ [Deployd.com](http://deployd.com) - Open source PaaS for quick API backend generation\n\nand [many more](https://npmjs.org/browse/depended/shelljs).\n\n## Installing\n\nVia npm:\n\n```bash\n$ npm install [-g] shelljs\n```\n\nIf the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to\nrun ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:\n\n```bash\n$ shjs my_script\n```\n\nYou can also just copy `shell.js` into your project's directory, and `require()` accordingly.\n\n\n## Examples\n\n### JavaScript\n\n```javascript\nrequire('shelljs/global');\n\nif (!which('git')) {\n echo('Sorry, this script requires git');\n exit(1);\n}\n\n// Copy files to release dir\nmkdir('-p', 'out/Release');\ncp('-R', 'stuff/*', 'out/Release');\n\n// Replace macros in each .js file\ncd('lib');\nls('*.js').forEach(function(file) {\n sed('-i', 'BUILD_VERSION', 'v0.1.2', file);\n sed('-i', /.*REMOVE_THIS_LINE.*\\n/, '', file);\n sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat('macro.js'), file);\n});\ncd('..');\n\n// Run external tool synchronously\nif (exec('git commit -am \"Auto-commit\"').code !== 0) {\n echo('Error: Git commit failed');\n exit(1);\n}\n```\n\n### CoffeeScript\n\n```coffeescript\nrequire 'shelljs/global'\n\nif not which 'git'\n echo 'Sorry, this script requires git'\n exit 1\n\n# Copy files to release dir\nmkdir '-p', 'out/Release'\ncp '-R', 'stuff/*', 'out/Release'\n\n# Replace macros in each .js file\ncd 'lib'\nfor file in ls '*.js'\n sed '-i', 'BUILD_VERSION', 'v0.1.2', file\n sed '-i', /.*REMOVE_THIS_LINE.*\\n/, '', file\n sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\\n/, cat 'macro.js', file\ncd '..'\n\n# Run external tool synchronously\nif (exec 'git commit -am \"Auto-commit\"').code != 0\n echo 'Error: Git commit failed'\n exit 1\n```\n\n## Global vs. Local\n\nThe example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.\n\nExample:\n\n```javascript\nvar shell = require('shelljs');\nshell.echo('hello world');\n```\n\n## Make tool\n\nA convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script.\n\nExample (CoffeeScript):\n\n```coffeescript\nrequire 'shelljs/make'\n\ntarget.all = ->\n target.bundle()\n target.docs()\n\ntarget.bundle = ->\n cd __dirname\n mkdir 'build'\n cd 'lib'\n (cat '*.js').to '../build/output.js'\n\ntarget.docs = ->\n cd __dirname\n mkdir 'docs'\n cd 'lib'\n for file in ls '*.js'\n text = grep '//@', file # extract special comments\n text.replace '//@', '' # remove comment tags\n text.to 'docs/my_docs.md'\n```\n\nTo run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.\n\n\n\n\n\n\n## Command reference\n\n\nAll commands run synchronously, unless otherwise stated.\n\n\n### cd('dir')\nChanges to directory `dir` for the duration of the script\n\n### pwd()\nReturns the current directory.\n\n### ls([options ,] path [,path ...])\n### ls([options ,] path_array)\nAvailable options:\n\n+ `-R`: recursive\n+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)\n\nExamples:\n\n```javascript\nls('projs/*.js');\nls('-R', '/users/me', '/tmp');\nls('-R', ['/users/me', '/tmp']); // same as above\n```\n\nReturns array of files in the given path, or in current directory if no path provided.\n\n### find(path [,path ...])\n### find(path_array)\nExamples:\n\n```javascript\nfind('src', 'lib');\nfind(['src', 'lib']); // same as above\nfind('.').filter(function(file) { return file.match(/\\.js$/); });\n```\n\nReturns array of all files (however deep) in the given paths.\n\nThe main difference from `ls('-R', path)` is that the resulting file names\ninclude the base directories, e.g. `lib/resources/file1` instead of just `file1`.\n\n### cp([options ,] source [,source ...], dest)\n### cp([options ,] source_array, dest)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\ncp('file1', 'dir1');\ncp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');\ncp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above\n```\n\nCopies files. The wildcard `*` is accepted.\n\n### rm([options ,] file [, file ...])\n### rm([options ,] file_array)\nAvailable options:\n\n+ `-f`: force\n+ `-r, -R`: recursive\n\nExamples:\n\n```javascript\nrm('-rf', '/tmp/*');\nrm('some_file.txt', 'another_file.txt');\nrm(['some_file.txt', 'another_file.txt']); // same as above\n```\n\nRemoves files. The wildcard `*` is accepted.\n\n### mv(source [, source ...], dest')\n### mv(source_array, dest')\nAvailable options:\n\n+ `f`: force\n\nExamples:\n\n```javascript\nmv('-f', 'file', 'dir/');\nmv('file1', 'file2', 'dir/');\nmv(['file1', 'file2'], 'dir/'); // same as above\n```\n\nMoves files. The wildcard `*` is accepted.\n\n### mkdir([options ,] dir [, dir ...])\n### mkdir([options ,] dir_array)\nAvailable options:\n\n+ `p`: full path (will create intermediate dirs if necessary)\n\nExamples:\n\n```javascript\nmkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');\nmkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above\n```\n\nCreates directories.\n\n### test(expression)\nAvailable expression primaries:\n\n+ `'-b', 'path'`: true if path is a block device\n+ `'-c', 'path'`: true if path is a character device\n+ `'-d', 'path'`: true if path is a directory\n+ `'-e', 'path'`: true if path exists\n+ `'-f', 'path'`: true if path is a regular file\n+ `'-L', 'path'`: true if path is a symboilc link\n+ `'-p', 'path'`: true if path is a pipe (FIFO)\n+ `'-S', 'path'`: true if path is a socket\n\nExamples:\n\n```javascript\nif (test('-d', path)) { /* do something with dir */ };\nif (!test('-f', path)) continue; // skip if it's a regular file\n```\n\nEvaluates expression using the available primaries and returns corresponding value.\n\n### cat(file [, file ...])\n### cat(file_array)\n\nExamples:\n\n```javascript\nvar str = cat('file*.txt');\nvar str = cat('file1', 'file2');\nvar str = cat(['file1', 'file2']); // same as above\n```\n\nReturns a string containing the given file, or a concatenated string\ncontaining the files if more than one file is given (a new line character is\nintroduced between each file). Wildcard `*` accepted.\n\n### 'string'.to(file)\n\nExamples:\n\n```javascript\ncat('input.txt').to('output.txt');\n```\n\nAnalogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as\nthose returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_\n\n### sed([options ,] search_regex, replace_str, file)\nAvailable options:\n\n+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_\n\nExamples:\n\n```javascript\nsed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');\nsed(/.*DELETE_THIS_LINE.*\\n/, '', 'source.js');\n```\n\nReads an input string from `file` and performs a JavaScript `replace()` on the input\nusing the given search regex and replacement string. Returns the new string after replacement.\n\n### grep([options ,] regex_filter, file [, file ...])\n### grep([options ,] regex_filter, file_array)\nAvailable options:\n\n+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria.\n\nExamples:\n\n```javascript\ngrep('-v', 'GLOBAL_VARIABLE', '*.js');\ngrep('GLOBAL_VARIABLE', '*.js');\n```\n\nReads input string from given files and returns a string containing all lines of the\nfile that match the given `regex_filter`. Wildcard `*` accepted.\n\n### which(command)\n\nExamples:\n\n```javascript\nvar nodeExec = which('node');\n```\n\nSearches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.\nReturns string containing the absolute path to the command.\n\n### echo(string [,string ...])\n\nExamples:\n\n```javascript\necho('hello world');\nvar str = echo('hello world');\n```\n\nPrints string to stdout, and returns string with additional utility methods\nlike `.to()`.\n\n### dirs([options | '+N' | '-N'])\n\nAvailable options:\n\n+ `-c`: Clears the directory stack by deleting all of the elements.\n\nArguments:\n\n+ `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.\n+ `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.\n\nDisplay the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.\n\nSee also: pushd, popd\n\n### pushd([options,] [dir | '-N' | '+N'])\n\nAvailable options:\n\n+ `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.\n\nArguments:\n\n+ `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.\n+ `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.\n+ `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.\n\nExamples:\n\n```javascript\n// process.cwd() === '/usr'\npushd('/etc'); // Returns /etc /usr\npushd('+1'); // Returns /usr /etc\n```\n\nSave the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.\n\n### popd([options,] ['-N' | '+N'])\n\nAvailable options:\n\n+ `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.\n\nArguments:\n\n+ `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.\n+ `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.\n\nExamples:\n\n```javascript\necho(process.cwd()); // '/usr'\npushd('/etc'); // '/etc /usr'\necho(process.cwd()); // '/etc'\npopd(); // '/usr'\necho(process.cwd()); // '/usr'\n```\n\nWhen no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.\n\n### exit(code)\nExits the current process with the given exit code.\n\n### env['VAR_NAME']\nObject containing environment variables (both getter and setter). Shortcut to process.env.\n\n### exec(command [, options] [, callback])\nAvailable options (all `false` by default):\n\n+ `async`: Asynchronous execution. Defaults to true if a callback is provided.\n+ `silent`: Do not echo program output to console.\n\nExamples:\n\n```javascript\nvar version = exec('node --version', {silent:true}).output;\n\nvar child = exec('some_long_running_process', {async:true});\nchild.stdout.on('data', function(data) {\n /* ... do something with data ... */\n});\n\nexec('some_long_running_process', function(code, output) {\n console.log('Exit code:', code);\n console.log('Program output:', output);\n});\n```\n\nExecutes the given `command` _synchronously_, unless otherwise specified.\nWhen in synchronous mode returns the object `{ code:..., output:... }`, containing the program's\n`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and\nthe `callback` gets the arguments `(code, output)`.\n\n**Note:** For long-lived processes, it's best to run `exec()` asynchronously as\nthe current synchronous implementation uses a lot of CPU. This should be getting\nfixed soon.\n\n### chmod(octal_mode || octal_string, file)\n### chmod(symbolic_mode, file)\n\nAvailable options:\n\n+ `-v`: output a diagnostic for every file processed\n+ `-c`: like verbose but report only when a change is made\n+ `-R`: change files and directories recursively\n\nExamples:\n\n```javascript\nchmod(755, '/Users/brandon');\nchmod('755', '/Users/brandon'); // same as above \nchmod('u+x', '/Users/brandon');\n```\n\nAlters the permissions of a file or directory by either specifying the\nabsolute permissions in octal form or expressing the changes in symbols.\nThis command tries to mimic the POSIX behavior as much as possible.\nNotable exceptions:\n\n+ In symbolic modes, 'a-r' and '-r' are identical. No consideration is\n given to the umask.\n+ There is no \"quiet\" option since default behavior is to run silent.\n\n## Configuration\n\n\n### config.silent\nExample:\n\n```javascript\nvar silentState = config.silent; // save old silent state\nconfig.silent = true;\n/* ... */\nconfig.silent = silentState; // restore old silent state\n```\n\nSuppresses all command output if `true`, except for `echo()` calls.\nDefault is `false`.\n\n### config.fatal\nExample:\n\n```javascript\nconfig.fatal = true;\ncp('this_file_does_not_exist', '/dev/null'); // dies here\n/* more commands... */\n```\n\nIf `true` the script will die on errors. Default is `false`.\n\n## Non-Unix commands\n\n\n### tempdir()\nSearches and returns string containing a writeable, platform-dependent temporary directory.\nFollows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).\n\n### error()\nTests if error occurred in the last command. Returns `null` if no error occurred,\notherwise returns string explaining the error\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/arturadib/shelljs/issues" + }, + "_id": "shelljs@0.1.4", + "dist": { + "shasum": "861665dc58ce461a0880be14ce9285cb9b71ae6c" + }, + "_from": "shelljs@0.1.x", + "_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/docs.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/docs.js new file mode 100755 index 000000000..68a2138e5 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/docs.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +require('../global'); + +echo('Appending docs to README.md'); + +cd(__dirname + '/..'); + +// Extract docs from shell.js +var docs = grep('//@', 'shell.js'); +// Remove '//@' +docs = docs.replace(/\/\/\@ ?/g, ''); +// Append docs to README +sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md'); + +echo('All done.'); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/run-tests.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/run-tests.js new file mode 100755 index 000000000..a9d32fcac --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/scripts/run-tests.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node +require('../global'); + +var path = require('path'); + +var failed = false; + +// +// Lint +// +JSHINT_BIN = './node_modules/jshint/bin/jshint'; +cd(__dirname + '/..'); + +if (!test('-f', JSHINT_BIN)) { + echo('JSHint not found. Run `npm install` in the root dir first.'); + exit(1); +} + +if (exec(JSHINT_BIN + ' --config jshint.json *.js test/*.js').code !== 0) { + failed = true; + echo('*** JSHINT FAILED! (return code != 0)'); + echo(); +} else { + echo('All JSHint tests passed'); + echo(); +} + +// +// Unit tests +// +cd(__dirname + '/../test'); +ls('*.js').forEach(function(file) { + echo('Running test:', file); + if (exec('node ' + file).code !== 123) { // 123 avoids false positives (e.g. premature exit) + failed = true; + echo('*** TEST FAILED! (missing exit code "123")'); + echo(); + } +}); + +if (failed) { + echo(); + echo('*******************************************************'); + echo('WARNING: Some tests did not pass!'); + echo('*******************************************************'); + exit(1); +} else { + echo(); + echo('All tests passed.'); +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/shell.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/shell.js new file mode 100644 index 000000000..7a4f4c8ac --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/shell.js @@ -0,0 +1,1901 @@ +// +// ShellJS +// Unix shell commands on top of Node's API +// +// Copyright (c) 2012 Artur Adib +// http://github.com/arturadib/shelljs +// + +var fs = require('fs'), + path = require('path'), + util = require('util'), + vm = require('vm'), + child = require('child_process'), + os = require('os'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +var config = { + silent: false, + fatal: false +}; + +var state = { + error: null, + currentCmd: 'shell.js', + tempDir: null + }, + platform = os.type().match(/^Win/) ? 'win' : 'unix'; + + +//@ +//@ All commands run synchronously, unless otherwise stated. +//@ + + +//@ +//@ ### cd('dir') +//@ Changes to directory `dir` for the duration of the script +function _cd(options, dir) { + if (!dir) + error('directory not specified'); + + if (!fs.existsSync(dir)) + error('no such file or directory: ' + dir); + + if (!fs.statSync(dir).isDirectory()) + error('not a directory: ' + dir); + + process.chdir(dir); +} +exports.cd = wrap('cd', _cd); + +//@ +//@ ### pwd() +//@ Returns the current directory. +function _pwd(options) { + var pwd = path.resolve(process.cwd()); + return ShellString(pwd); +} +exports.pwd = wrap('pwd', _pwd); + + +//@ +//@ ### ls([options ,] path [,path ...]) +//@ ### ls([options ,] path_array) +//@ Available options: +//@ +//@ + `-R`: recursive +//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ ls('projs/*.js'); +//@ ls('-R', '/users/me', '/tmp'); +//@ ls('-R', ['/users/me', '/tmp']); // same as above +//@ ``` +//@ +//@ Returns array of files in the given path, or in current directory if no path provided. +function _ls(options, paths) { + options = parseOptions(options, { + 'R': 'recursive', + 'A': 'all', + 'a': 'all_deprecated' + }); + + if (options.all_deprecated) { + // We won't support the -a option as it's hard to image why it's useful + // (it includes '.' and '..' in addition to '.*' files) + // For backwards compatibility we'll dump a deprecated message and proceed as before + log('ls: Option -a is deprecated. Use -A instead'); + options.all = true; + } + + if (!paths) + paths = ['.']; + else if (typeof paths === 'object') + paths = paths; // assume array + else if (typeof paths === 'string') + paths = [].slice.call(arguments, 1); + + var list = []; + + // Conditionally pushes file to list - returns true if pushed, false otherwise + // (e.g. prevents hidden files to be included unless explicitly told so) + function pushFile(file, query) { + // hidden file? + if (path.basename(file)[0] === '.') { + // not explicitly asking for hidden files? + if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1)) + return false; + } + + if (platform === 'win') + file = file.replace(/\\/g, '/'); + + list.push(file); + return true; + } + + paths.forEach(function(p) { + if (fs.existsSync(p)) { + var stats = fs.statSync(p); + // Simple file? + if (stats.isFile()) { + pushFile(p, p); + return; // continue + } + + // Simple dir? + if (stats.isDirectory()) { + // Iterate over p contents + fs.readdirSync(p).forEach(function(file) { + if (!pushFile(file, p)) + return; + + // Recursive? + if (options.recursive) { + var oldDir = _pwd(); + _cd('', p); + if (fs.statSync(file).isDirectory()) + list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*')); + _cd('', oldDir); + } + }); + return; // continue + } + } + + // p does not exist - possible wildcard present + + var basename = path.basename(p); + var dirname = path.dirname(p); + // Wildcard present on an existing dir? (e.g. '/tmp/*.js') + if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) { + // Escape special regular expression chars + var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1'); + // Translates wildcard into regex + regexp = '^' + regexp.replace(/\*/g, '.*') + '$'; + // Iterate over directory contents + fs.readdirSync(dirname).forEach(function(file) { + if (file.match(new RegExp(regexp))) { + if (!pushFile(path.normalize(dirname+'/'+file), basename)) + return; + + // Recursive? + if (options.recursive) { + var pp = dirname + '/' + file; + if (fs.lstatSync(pp).isDirectory()) + list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*')); + } // recursive + } // if file matches + }); // forEach + return; + } + + error('no such file or directory: ' + p, true); + }); + + return list; +} +exports.ls = wrap('ls', _ls); + + +//@ +//@ ### find(path [,path ...]) +//@ ### find(path_array) +//@ Examples: +//@ +//@ ```javascript +//@ find('src', 'lib'); +//@ find(['src', 'lib']); // same as above +//@ find('.').filter(function(file) { return file.match(/\.js$/); }); +//@ ``` +//@ +//@ Returns array of all files (however deep) in the given paths. +//@ +//@ The main difference from `ls('-R', path)` is that the resulting file names +//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`. +function _find(options, paths) { + if (!paths) + error('no path specified'); + else if (typeof paths === 'object') + paths = paths; // assume array + else if (typeof paths === 'string') + paths = [].slice.call(arguments, 1); + + var list = []; + + function pushFile(file) { + if (platform === 'win') + file = file.replace(/\\/g, '/'); + list.push(file); + } + + // why not simply do ls('-R', paths)? because the output wouldn't give the base dirs + // to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory + + paths.forEach(function(file) { + pushFile(file); + + if (fs.statSync(file).isDirectory()) { + _ls('-RA', file+'/*').forEach(function(subfile) { + pushFile(subfile); + }); + } + }); + + return list; +} +exports.find = wrap('find', _find); + + +//@ +//@ ### cp([options ,] source [,source ...], dest) +//@ ### cp([options ,] source_array, dest) +//@ Available options: +//@ +//@ + `-f`: force +//@ + `-r, -R`: recursive +//@ +//@ Examples: +//@ +//@ ```javascript +//@ cp('file1', 'dir1'); +//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); +//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above +//@ ``` +//@ +//@ Copies files. The wildcard `*` is accepted. +function _cp(options, sources, dest) { + options = parseOptions(options, { + 'f': 'force', + 'R': 'recursive', + 'r': 'recursive' + }); + + // Get sources, dest + if (arguments.length < 3) { + error('missing and/or '); + } else if (arguments.length > 3) { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } else if (typeof sources === 'string') { + sources = [sources]; + } else if ('length' in sources) { + sources = sources; // no-op for array + } else { + error('invalid arguments'); + } + + var exists = fs.existsSync(dest), + stats = exists && fs.statSync(dest); + + // Dest is not existing dir, but multiple sources given + if ((!exists || !stats.isDirectory()) && sources.length > 1) + error('dest is not a directory (too many sources)'); + + // Dest is an existing file, but no -f given + if (exists && stats.isFile() && !options.force) + error('dest file already exists: ' + dest); + + if (options.recursive) { + // Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*" + // (see Github issue #15) + sources.forEach(function(src, i) { + if (src[src.length - 1] === '/') + sources[i] += '*'; + }); + + // Create dest + try { + fs.mkdirSync(dest, parseInt('0777', 8)); + } catch (e) { + // like Unix's cp, keep going even if we can't create dest dir + } + } + + sources = expand(sources); + + sources.forEach(function(src) { + if (!fs.existsSync(src)) { + error('no such file or directory: '+src, true); + return; // skip file + } + + // If here, src exists + if (fs.statSync(src).isDirectory()) { + if (!options.recursive) { + // Non-Recursive + log(src + ' is a directory (not copied)'); + } else { + // Recursive + // 'cp /a/source dest' should create 'source' in 'dest' + var newDest = path.join(dest, path.basename(src)), + checkDir = fs.statSync(src); + try { + fs.mkdirSync(newDest, checkDir.mode); + } catch (e) { + //if the directory already exists, that's okay + if (e.code !== 'EEXIST') throw e; + } + + cpdirSyncRecursive(src, newDest, {force: options.force}); + } + return; // done with dir + } + + // If here, src is a file + + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) + thisDest = path.normalize(dest + '/' + path.basename(src)); + + if (fs.existsSync(thisDest) && !options.force) { + error('dest file already exists: ' + thisDest, true); + return; // skip file + } + + copyFileSync(src, thisDest); + }); // forEach(src) +} +exports.cp = wrap('cp', _cp); + +//@ +//@ ### rm([options ,] file [, file ...]) +//@ ### rm([options ,] file_array) +//@ Available options: +//@ +//@ + `-f`: force +//@ + `-r, -R`: recursive +//@ +//@ Examples: +//@ +//@ ```javascript +//@ rm('-rf', '/tmp/*'); +//@ rm('some_file.txt', 'another_file.txt'); +//@ rm(['some_file.txt', 'another_file.txt']); // same as above +//@ ``` +//@ +//@ Removes files. The wildcard `*` is accepted. +function _rm(options, files) { + options = parseOptions(options, { + 'f': 'force', + 'r': 'recursive', + 'R': 'recursive' + }); + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 1); + // if it's array leave it as it is + + files = expand(files); + + files.forEach(function(file) { + if (!fs.existsSync(file)) { + // Path does not exist, no force flag given + if (!options.force) + error('no such file or directory: '+file, true); + + return; // skip file + } + + // If here, path exists + + var stats = fs.statSync(file); + // Remove simple file + if (stats.isFile()) { + + // Do not check for file writing permissions + if (options.force) { + _unlinkSync(file); + return; + } + + if (isWriteable(file)) + _unlinkSync(file); + else + error('permission denied: '+file, true); + + return; + } // simple file + + // Path is an existing directory, but no -r flag given + if (stats.isDirectory() && !options.recursive) { + error('path is a directory', true); + return; // skip path + } + + // Recursively remove existing directory + if (stats.isDirectory() && options.recursive) { + rmdirSyncRecursive(file, options.force); + } + }); // forEach(file) +} // rm +exports.rm = wrap('rm', _rm); + +//@ +//@ ### mv(source [, source ...], dest') +//@ ### mv(source_array, dest') +//@ Available options: +//@ +//@ + `f`: force +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mv('-f', 'file', 'dir/'); +//@ mv('file1', 'file2', 'dir/'); +//@ mv(['file1', 'file2'], 'dir/'); // same as above +//@ ``` +//@ +//@ Moves files. The wildcard `*` is accepted. +function _mv(options, sources, dest) { + options = parseOptions(options, { + 'f': 'force' + }); + + // Get sources, dest + if (arguments.length < 3) { + error('missing and/or '); + } else if (arguments.length > 3) { + sources = [].slice.call(arguments, 1, arguments.length - 1); + dest = arguments[arguments.length - 1]; + } else if (typeof sources === 'string') { + sources = [sources]; + } else if ('length' in sources) { + sources = sources; // no-op for array + } else { + error('invalid arguments'); + } + + sources = expand(sources); + + var exists = fs.existsSync(dest), + stats = exists && fs.statSync(dest); + + // Dest is not existing dir, but multiple sources given + if ((!exists || !stats.isDirectory()) && sources.length > 1) + error('dest is not a directory (too many sources)'); + + // Dest is an existing file, but no -f given + if (exists && stats.isFile() && !options.force) + error('dest file already exists: ' + dest); + + sources.forEach(function(src) { + if (!fs.existsSync(src)) { + error('no such file or directory: '+src, true); + return; // skip file + } + + // If here, src exists + + // When copying to '/path/dir': + // thisDest = '/path/dir/file1' + var thisDest = dest; + if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) + thisDest = path.normalize(dest + '/' + path.basename(src)); + + if (fs.existsSync(thisDest) && !options.force) { + error('dest file already exists: ' + thisDest, true); + return; // skip file + } + + if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { + error('cannot move to self: '+src, true); + return; // skip file + } + + fs.renameSync(src, thisDest); + }); // forEach(src) +} // mv +exports.mv = wrap('mv', _mv); + +//@ +//@ ### mkdir([options ,] dir [, dir ...]) +//@ ### mkdir([options ,] dir_array) +//@ Available options: +//@ +//@ + `p`: full path (will create intermediate dirs if necessary) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); +//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above +//@ ``` +//@ +//@ Creates directories. +function _mkdir(options, dirs) { + options = parseOptions(options, { + 'p': 'fullpath' + }); + if (!dirs) + error('no paths given'); + + if (typeof dirs === 'string') + dirs = [].slice.call(arguments, 1); + // if it's array leave it as it is + + dirs.forEach(function(dir) { + if (fs.existsSync(dir)) { + if (!options.fullpath) + error('path already exists: ' + dir, true); + return; // skip dir + } + + // Base dir does not exist, and no -p option given + var baseDir = path.dirname(dir); + if (!fs.existsSync(baseDir) && !options.fullpath) { + error('no such file or directory: ' + baseDir, true); + return; // skip dir + } + + if (options.fullpath) + mkdirSyncRecursive(dir); + else + fs.mkdirSync(dir, parseInt('0777', 8)); + }); +} // mkdir +exports.mkdir = wrap('mkdir', _mkdir); + +//@ +//@ ### test(expression) +//@ Available expression primaries: +//@ +//@ + `'-b', 'path'`: true if path is a block device +//@ + `'-c', 'path'`: true if path is a character device +//@ + `'-d', 'path'`: true if path is a directory +//@ + `'-e', 'path'`: true if path exists +//@ + `'-f', 'path'`: true if path is a regular file +//@ + `'-L', 'path'`: true if path is a symboilc link +//@ + `'-p', 'path'`: true if path is a pipe (FIFO) +//@ + `'-S', 'path'`: true if path is a socket +//@ +//@ Examples: +//@ +//@ ```javascript +//@ if (test('-d', path)) { /* do something with dir */ }; +//@ if (!test('-f', path)) continue; // skip if it's a regular file +//@ ``` +//@ +//@ Evaluates expression using the available primaries and returns corresponding value. +function _test(options, path) { + if (!path) + error('no path given'); + + // hack - only works with unary primaries + options = parseOptions(options, { + 'b': 'block', + 'c': 'character', + 'd': 'directory', + 'e': 'exists', + 'f': 'file', + 'L': 'link', + 'p': 'pipe', + 'S': 'socket' + }); + + var canInterpret = false; + for (var key in options) + if (options[key] === true) { + canInterpret = true; + break; + } + + if (!canInterpret) + error('could not interpret expression'); + + if (options.link) { + try { + return fs.lstatSync(path).isSymbolicLink(); + } catch(e) { + return false; + } + } + + if (!fs.existsSync(path)) + return false; + + if (options.exists) + return true; + + var stats = fs.statSync(path); + + if (options.block) + return stats.isBlockDevice(); + + if (options.character) + return stats.isCharacterDevice(); + + if (options.directory) + return stats.isDirectory(); + + if (options.file) + return stats.isFile(); + + if (options.pipe) + return stats.isFIFO(); + + if (options.socket) + return stats.isSocket(); +} // test +exports.test = wrap('test', _test); + + +//@ +//@ ### cat(file [, file ...]) +//@ ### cat(file_array) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var str = cat('file*.txt'); +//@ var str = cat('file1', 'file2'); +//@ var str = cat(['file1', 'file2']); // same as above +//@ ``` +//@ +//@ Returns a string containing the given file, or a concatenated string +//@ containing the files if more than one file is given (a new line character is +//@ introduced between each file). Wildcard `*` accepted. +function _cat(options, files) { + var cat = ''; + + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 1); + // if it's array leave it as it is + + files = expand(files); + + files.forEach(function(file) { + if (!fs.existsSync(file)) + error('no such file or directory: ' + file); + + cat += fs.readFileSync(file, 'utf8') + '\n'; + }); + + if (cat[cat.length-1] === '\n') + cat = cat.substring(0, cat.length-1); + + return ShellString(cat); +} +exports.cat = wrap('cat', _cat); + +//@ +//@ ### 'string'.to(file) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ cat('input.txt').to('output.txt'); +//@ ``` +//@ +//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as +//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ +function _to(options, file) { + if (!file) + error('wrong arguments'); + + if (!fs.existsSync( path.dirname(file) )) + error('no such file or directory: ' + path.dirname(file)); + + try { + fs.writeFileSync(file, this.toString(), 'utf8'); + } catch(e) { + error('could not write to file (code '+e.code+'): '+file, true); + } +} +// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings. +// For now, this is a dummy function to bookmark places we need such strings +function ShellString(str) { + return str; +} +String.prototype.to = wrap('to', _to); + +//@ +//@ ### sed([options ,] search_regex, replace_str, file) +//@ Available options: +//@ +//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ +//@ +//@ Examples: +//@ +//@ ```javascript +//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); +//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); +//@ ``` +//@ +//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input +//@ using the given search regex and replacement string. Returns the new string after replacement. +function _sed(options, regex, replacement, file) { + options = parseOptions(options, { + 'i': 'inplace' + }); + + if (typeof replacement === 'string') + replacement = replacement; // no-op + else if (typeof replacement === 'number') + replacement = replacement.toString(); // fallback + else + error('invalid replacement string'); + + if (!file) + error('no file given'); + + if (!fs.existsSync(file)) + error('no such file or directory: ' + file); + + var result = fs.readFileSync(file, 'utf8').replace(regex, replacement); + if (options.inplace) + fs.writeFileSync(file, result, 'utf8'); + + return ShellString(result); +} +exports.sed = wrap('sed', _sed); + +//@ +//@ ### grep([options ,] regex_filter, file [, file ...]) +//@ ### grep([options ,] regex_filter, file_array) +//@ Available options: +//@ +//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); +//@ grep('GLOBAL_VARIABLE', '*.js'); +//@ ``` +//@ +//@ Reads input string from given files and returns a string containing all lines of the +//@ file that match the given `regex_filter`. Wildcard `*` accepted. +function _grep(options, regex, files) { + options = parseOptions(options, { + 'v': 'inverse' + }); + + if (!files) + error('no paths given'); + + if (typeof files === 'string') + files = [].slice.call(arguments, 2); + // if it's array leave it as it is + + files = expand(files); + + var grep = ''; + files.forEach(function(file) { + if (!fs.existsSync(file)) { + error('no such file or directory: ' + file, true); + return; + } + + var contents = fs.readFileSync(file, 'utf8'), + lines = contents.split(/\r*\n/); + lines.forEach(function(line) { + var matched = line.match(regex); + if ((options.inverse && !matched) || (!options.inverse && matched)) + grep += line + '\n'; + }); + }); + + return ShellString(grep); +} +exports.grep = wrap('grep', _grep); + + +//@ +//@ ### which(command) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var nodeExec = which('node'); +//@ ``` +//@ +//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. +//@ Returns string containing the absolute path to the command. +function _which(options, cmd) { + if (!cmd) + error('must specify command'); + + var pathEnv = process.env.path || process.env.Path || process.env.PATH, + pathArray = splitPath(pathEnv), + where = null; + + // No relative/absolute paths provided? + if (cmd.search(/\//) === -1) { + // Search for command in PATH + pathArray.forEach(function(dir) { + if (where) + return; // already found it + + var attempt = path.resolve(dir + '/' + cmd); + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + + if (platform === 'win') { + var baseAttempt = attempt; + attempt = baseAttempt + '.exe'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + attempt = baseAttempt + '.cmd'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + attempt = baseAttempt + '.bat'; + if (fs.existsSync(attempt)) { + where = attempt; + return; + } + } // if 'win' + }); + } + + // Command not found anywhere? + if (!fs.existsSync(cmd) && !where) + return null; + + where = where || path.resolve(cmd); + + return ShellString(where); +} +exports.which = wrap('which', _which); + +//@ +//@ ### echo(string [,string ...]) +//@ +//@ Examples: +//@ +//@ ```javascript +//@ echo('hello world'); +//@ var str = echo('hello world'); +//@ ``` +//@ +//@ Prints string to stdout, and returns string with additional utility methods +//@ like `.to()`. +function _echo() { + var messages = [].slice.call(arguments, 0); + console.log.apply(this, messages); + return ShellString(messages.join(' ')); +} +exports.echo = _echo; // don't wrap() as it could parse '-options' + +// Pushd/popd/dirs internals +var _dirStack = []; + +function _isStackIndex(index) { + return (/^[\-+]\d+$/).test(index); +} + +function _parseStackIndex(index) { + if (_isStackIndex(index)) { + if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd + return (/^-/).test(index) ? Number(index) - 1 : Number(index); + } else { + error(index + ': directory stack index out of range'); + } + } else { + error(index + ': invalid number'); + } +} + +function _actualDirStack() { + return [process.cwd()].concat(_dirStack); +} + +//@ +//@ ### dirs([options | '+N' | '-N']) +//@ +//@ Available options: +//@ +//@ + `-c`: Clears the directory stack by deleting all of the elements. +//@ +//@ Arguments: +//@ +//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero. +//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero. +//@ +//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified. +//@ +//@ See also: pushd, popd +function _dirs(options, index) { + if (_isStackIndex(options)) { + index = options; + options = ''; + } + + options = parseOptions(options, { + 'c' : 'clear' + }); + + if (options['clear']) { + _dirStack = []; + return _dirStack; + } + + var stack = _actualDirStack(); + + if (index) { + index = _parseStackIndex(index); + + if (index < 0) { + index = stack.length + index; + } + + log(stack[index]); + return stack[index]; + } + + log(stack.join(' ')); + + return stack; +} +exports.dirs = wrap("dirs", _dirs); + +//@ +//@ ### pushd([options,] [dir | '-N' | '+N']) +//@ +//@ Available options: +//@ +//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated. +//@ +//@ Arguments: +//@ +//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`. +//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. +//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ // process.cwd() === '/usr' +//@ pushd('/etc'); // Returns /etc /usr +//@ pushd('+1'); // Returns /usr /etc +//@ ``` +//@ +//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack. +function _pushd(options, dir) { + if (_isStackIndex(options)) { + dir = options; + options = ''; + } + + options = parseOptions(options, { + 'n' : 'no-cd' + }); + + var dirs = _actualDirStack(); + + if (dir === '+0') { + return dirs; // +0 is a noop + } else if (!dir) { + if (dirs.length > 1) { + dirs = dirs.splice(1, 1).concat(dirs); + } else { + return error('no other directory'); + } + } else if (_isStackIndex(dir)) { + var n = _parseStackIndex(dir); + dirs = dirs.slice(n).concat(dirs.slice(0, n)); + } else { + if (options['no-cd']) { + dirs.splice(1, 0, dir); + } else { + dirs.unshift(dir); + } + } + + if (options['no-cd']) { + dirs = dirs.slice(1); + } else { + dir = path.resolve(dirs.shift()); + _cd('', dir); + } + + _dirStack = dirs; + return _dirs(''); +} +exports.pushd = wrap('pushd', _pushd); + +//@ +//@ ### popd([options,] ['-N' | '+N']) +//@ +//@ Available options: +//@ +//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated. +//@ +//@ Arguments: +//@ +//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero. +//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ echo(process.cwd()); // '/usr' +//@ pushd('/etc'); // '/etc /usr' +//@ echo(process.cwd()); // '/etc' +//@ popd(); // '/usr' +//@ echo(process.cwd()); // '/usr' +//@ ``` +//@ +//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack. +function _popd(options, index) { + if (_isStackIndex(options)) { + index = options; + options = ''; + } + + options = parseOptions(options, { + 'n' : 'no-cd' + }); + + if (!_dirStack.length) { + return error('directory stack empty'); + } + + index = _parseStackIndex(index || '+0'); + + if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) { + index = index > 0 ? index - 1 : index; + _dirStack.splice(index, 1); + } else { + var dir = path.resolve(_dirStack.shift()); + _cd('', dir); + } + + return _dirs(''); +} +exports.popd = wrap("popd", _popd); + +//@ +//@ ### exit(code) +//@ Exits the current process with the given exit code. +exports.exit = process.exit; + +//@ +//@ ### env['VAR_NAME'] +//@ Object containing environment variables (both getter and setter). Shortcut to process.env. +exports.env = process.env; + +//@ +//@ ### exec(command [, options] [, callback]) +//@ Available options (all `false` by default): +//@ +//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided. +//@ + `silent`: Do not echo program output to console. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var version = exec('node --version', {silent:true}).output; +//@ +//@ var child = exec('some_long_running_process', {async:true}); +//@ child.stdout.on('data', function(data) { +//@ /* ... do something with data ... */ +//@ }); +//@ +//@ exec('some_long_running_process', function(code, output) { +//@ console.log('Exit code:', code); +//@ console.log('Program output:', output); +//@ }); +//@ ``` +//@ +//@ Executes the given `command` _synchronously_, unless otherwise specified. +//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's +//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and +//@ the `callback` gets the arguments `(code, output)`. +//@ +//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as +//@ the current synchronous implementation uses a lot of CPU. This should be getting +//@ fixed soon. +function _exec(command, options, callback) { + if (!command) + error('must specify command'); + + // Callback is defined instead of options. + if (typeof options === 'function') { + callback = options; + options = { async: true }; + } + + // Callback is defined with options. + if (typeof options === 'object' && typeof callback === 'function') { + options.async = true; + } + + options = extend({ + silent: config.silent, + async: false + }, options); + + if (options.async) + return execAsync(command, options, callback); + else + return execSync(command, options); +} +exports.exec = wrap('exec', _exec, {notUnix:true}); + +var PERMS = (function (base) { + return { + OTHER_EXEC : base.EXEC, + OTHER_WRITE : base.WRITE, + OTHER_READ : base.READ, + + GROUP_EXEC : base.EXEC << 3, + GROUP_WRITE : base.WRITE << 3, + GROUP_READ : base.READ << 3, + + OWNER_EXEC : base.EXEC << 6, + OWNER_WRITE : base.WRITE << 6, + OWNER_READ : base.READ << 6, + + // Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is + // the preferred way, else a jshint warning is thrown. + STICKY : parseInt('01000', 8), + SETGID : parseInt('02000', 8), + SETUID : parseInt('04000', 8), + + TYPE_MASK : parseInt('0770000', 8) + }; +})({ + EXEC : 1, + WRITE : 2, + READ : 4 +}); + + +//@ +//@ ### chmod(octal_mode || octal_string, file) +//@ ### chmod(symbolic_mode, file) +//@ +//@ Available options: +//@ +//@ + `-v`: output a diagnostic for every file processed//@ +//@ + `-c`: like verbose but report only when a change is made//@ +//@ + `-R`: change files and directories recursively//@ +//@ +//@ Examples: +//@ +//@ ```javascript +//@ chmod(755, '/Users/brandon'); +//@ chmod('755', '/Users/brandon'); // same as above +//@ chmod('u+x', '/Users/brandon'); +//@ ``` +//@ +//@ Alters the permissions of a file or directory by either specifying the +//@ absolute permissions in octal form or expressing the changes in symbols. +//@ This command tries to mimic the POSIX behavior as much as possible. +//@ Notable exceptions: +//@ +//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is +//@ given to the umask. +//@ + There is no "quiet" option since default behavior is to run silent. +function _chmod(options, mode, filePattern) { + if (!filePattern) { + if (options.length > 0 && options.charAt(0) === '-') { + // Special case where the specified file permissions started with - to subtract perms, which + // get picked up by the option parser as command flags. + // If we are down by one argument and options starts with -, shift everything over. + filePattern = mode; + mode = options; + options = ''; + } + else { + error('You must specify a file.'); + } + } + + options = parseOptions(options, { + 'R': 'recursive', + 'c': 'changes', + 'v': 'verbose' + }); + + if (typeof filePattern === 'string') { + filePattern = [ filePattern ]; + } + + var files; + + if (options.recursive) { + files = []; + expand(filePattern).forEach(function addFile(expandedFile) { + var stat = fs.lstatSync(expandedFile); + + if (!stat.isSymbolicLink()) { + files.push(expandedFile); + + if (stat.isDirectory()) { // intentionally does not follow symlinks. + fs.readdirSync(expandedFile).forEach(function (child) { + addFile(expandedFile + '/' + child); + }); + } + } + }); + } + else { + files = expand(filePattern); + } + + files.forEach(function innerChmod(file) { + file = path.resolve(file); + if (!fs.existsSync(file)) { + error('File not found: ' + file); + } + + // When recursing, don't follow symlinks. + if (options.recursive && fs.lstatSync(file).isSymbolicLink()) { + return; + } + + var perms = fs.statSync(file).mode; + var type = perms & PERMS.TYPE_MASK; + + var newPerms = perms; + + if (isNaN(parseInt(mode, 8))) { + // parse options + mode.split(',').forEach(function (symbolicMode) { + /*jshint regexdash:true */ + var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i; + var matches = pattern.exec(symbolicMode); + + if (matches) { + var applyTo = matches[1]; + var operator = matches[2]; + var change = matches[3]; + + var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === ''; + var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === ''; + var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === ''; + + var changeRead = change.indexOf('r') != -1; + var changeWrite = change.indexOf('w') != -1; + var changeExec = change.indexOf('x') != -1; + var changeSticky = change.indexOf('t') != -1; + var changeSetuid = change.indexOf('s') != -1; + + var mask = 0; + if (changeOwner) { + mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0); + } + if (changeGroup) { + mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0); + } + if (changeOther) { + mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0); + } + + // Sticky bit is special - it's not tied to user, group or other. + if (changeSticky) { + mask |= PERMS.STICKY; + } + + switch (operator) { + case '+': + newPerms |= mask; + break; + + case '-': + newPerms &= ~mask; + break; + + case '=': + newPerms = type + mask; + + // According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared. + if (fs.statSync(file).isDirectory()) { + newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; + } + break; + } + + if (options.verbose) { + log(file + ' -> ' + newPerms.toString(8)); + } + + if (perms != newPerms) { + if (!options.verbose && options.changes) { + log(file + ' -> ' + newPerms.toString(8)); + } + fs.chmodSync(file, newPerms); + } + } + else { + error('Invalid symbolic mode change: ' + symbolicMode); + } + }); + } + else { + // they gave us a full number + newPerms = type + parseInt(mode, 8); + + // POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared. + if (fs.statSync(file).isDirectory()) { + newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; + } + + fs.chmodSync(file, newPerms); + } + }); +} +exports.chmod = wrap('chmod', _chmod); + + +//@ +//@ ## Configuration +//@ + + + +exports.config = config; + +//@ +//@ ### config.silent +//@ Example: +//@ +//@ ```javascript +//@ var silentState = config.silent; // save old silent state +//@ config.silent = true; +//@ /* ... */ +//@ config.silent = silentState; // restore old silent state +//@ ``` +//@ +//@ Suppresses all command output if `true`, except for `echo()` calls. +//@ Default is `false`. + +//@ +//@ ### config.fatal +//@ Example: +//@ +//@ ```javascript +//@ config.fatal = true; +//@ cp('this_file_does_not_exist', '/dev/null'); // dies here +//@ /* more commands... */ +//@ ``` +//@ +//@ If `true` the script will die on errors. Default is `false`. + + + + +//@ +//@ ## Non-Unix commands +//@ + + + + + + +//@ +//@ ### tempdir() +//@ Searches and returns string containing a writeable, platform-dependent temporary directory. +//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). +exports.tempdir = wrap('tempdir', tempDir); + + +//@ +//@ ### error() +//@ Tests if error occurred in the last command. Returns `null` if no error occurred, +//@ otherwise returns string explaining the error +exports.error = function() { + return state.error; +}; + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// +// Auxiliary functions (internal use only) +// + +function log() { + if (!config.silent) + console.log.apply(this, arguments); +} + +function deprecate(what, msg) { + console.log('*** ShellJS.'+what+': This function is deprecated.', msg); +} + +function write(msg) { + if (!config.silent) + process.stdout.write(msg); +} + +// Shows error message. Throws unless _continue or config.fatal are true +function error(msg, _continue) { + if (state.error === null) + state.error = ''; + state.error += state.currentCmd + ': ' + msg + '\n'; + + log(state.error); + + if (config.fatal) + process.exit(1); + + if (!_continue) + throw ''; +} + +// Returns {'alice': true, 'bob': false} when passed: +// parseOptions('-a', {'a':'alice', 'b':'bob'}); +function parseOptions(str, map) { + if (!map) + error('parseOptions() internal error: no map given'); + + // All options are false by default + var options = {}; + for (var letter in map) + options[map[letter]] = false; + + if (!str) + return options; // defaults + + if (typeof str !== 'string') + error('parseOptions() internal error: wrong str'); + + // e.g. match[1] = 'Rf' for str = '-Rf' + var match = str.match(/^\-(.+)/); + if (!match) + return options; + + // e.g. chars = ['R', 'f'] + var chars = match[1].split(''); + + chars.forEach(function(c) { + if (c in map) + options[map[c]] = true; + else + error('option not recognized: '+c); + }); + + return options; +} + +// Common wrapper for all Unix-like commands +function wrap(cmd, fn, options) { + return function() { + var retValue = null; + + state.currentCmd = cmd; + state.error = null; + + try { + var args = [].slice.call(arguments, 0); + + if (options && options.notUnix) { + retValue = fn.apply(this, args); + } else { + if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-') + args.unshift(''); // only add dummy option if '-option' not already present + retValue = fn.apply(this, args); + } + } catch (e) { + if (!state.error) { + // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... + console.log('shell.js: internal error'); + console.log(e.stack || e); + process.exit(1); + } + if (config.fatal) + throw e; + } + + state.currentCmd = 'shell.js'; + return retValue; + }; +} // wrap + +// Buffered file copy, synchronous +// (Using readFileSync() + writeFileSync() could easily cause a memory overflow +// with large files) +function copyFileSync(srcFile, destFile) { + if (!fs.existsSync(srcFile)) + error('copyFileSync: no such file or directory: ' + srcFile); + + var BUF_LENGTH = 64*1024, + buf = new Buffer(BUF_LENGTH), + bytesRead = BUF_LENGTH, + pos = 0, + fdr = null, + fdw = null; + + try { + fdr = fs.openSync(srcFile, 'r'); + } catch(e) { + error('copyFileSync: could not read src file ('+srcFile+')'); + } + + try { + fdw = fs.openSync(destFile, 'w'); + } catch(e) { + error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile); + } + + while (bytesRead === BUF_LENGTH) { + bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos); + fs.writeSync(fdw, buf, 0, bytesRead); + pos += bytesRead; + } + + fs.closeSync(fdr); + fs.closeSync(fdw); +} + +// Recursively copies 'sourceDir' into 'destDir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function cpdirSyncRecursive(sourceDir, destDir, opts) { + if (!opts) opts = {}; + + /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ + var checkDir = fs.statSync(sourceDir); + try { + fs.mkdirSync(destDir, checkDir.mode); + } catch (e) { + //if the directory already exists, that's okay + if (e.code !== 'EEXIST') throw e; + } + + var files = fs.readdirSync(sourceDir); + + for(var i = 0; i < files.length; i++) { + var currFile = fs.lstatSync(sourceDir + "/" + files[i]); + + if (currFile.isDirectory()) { + /* recursion this thing right on back. */ + cpdirSyncRecursive(sourceDir + "/" + files[i], destDir + "/" + files[i], opts); + } else if (currFile.isSymbolicLink()) { + var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]); + fs.symlinkSync(symlinkFull, destDir + "/" + files[i]); + } else { + /* At this point, we've hit a file actually worth copying... so copy it on over. */ + if (fs.existsSync(destDir + "/" + files[i]) && !opts.force) { + log('skipping existing file: ' + files[i]); + } else { + copyFileSync(sourceDir + "/" + files[i], destDir + "/" + files[i]); + } + } + + } // for files +} // cpdirSyncRecursive + +// Recursively removes 'dir' +// Adapted from https://github.com/ryanmcgrath/wrench-js +// +// Copyright (c) 2010 Ryan McGrath +// Copyright (c) 2012 Artur Adib +// +// Licensed under the MIT License +// http://www.opensource.org/licenses/mit-license.php +function rmdirSyncRecursive(dir, force) { + var files; + + files = fs.readdirSync(dir); + + // Loop through and delete everything in the sub-tree after checking it + for(var i = 0; i < files.length; i++) { + var file = dir + "/" + files[i], + currFile = fs.lstatSync(file); + + if(currFile.isDirectory()) { // Recursive function back to the beginning + rmdirSyncRecursive(file, force); + } + + else if(currFile.isSymbolicLink()) { // Unlink symlinks + if (force || isWriteable(file)) { + try { + _unlinkSync(file); + } catch (e) { + error('could not remove file (code '+e.code+'): ' + file, true); + } + } + } + + else // Assume it's a file - perhaps a try/catch belongs here? + if (force || isWriteable(file)) { + try { + _unlinkSync(file); + } catch (e) { + error('could not remove file (code '+e.code+'): ' + file, true); + } + } + } + + // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. + // Huzzah for the shopkeep. + + var result; + try { + result = fs.rmdirSync(dir); + } catch(e) { + error('could not remove directory (code '+e.code+'): ' + dir, true); + } + + return result; +} // rmdirSyncRecursive + +// Recursively creates 'dir' +function mkdirSyncRecursive(dir) { + var baseDir = path.dirname(dir); + + // Base dir exists, no recursion necessary + if (fs.existsSync(baseDir)) { + fs.mkdirSync(dir, parseInt('0777', 8)); + return; + } + + // Base dir does not exist, go recursive + mkdirSyncRecursive(baseDir); + + // Base dir created, can create dir + fs.mkdirSync(dir, parseInt('0777', 8)); +} + +// e.g. 'shelljs_a5f185d0443ca...' +function randomFileName() { + function randomHash(count) { + if (count === 1) + return parseInt(16*Math.random(), 10).toString(16); + else { + var hash = ''; + for (var i=0; i&1'; // works on both win/unix + + var script = + "var child = require('child_process')," + + " fs = require('fs');" + + "child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {" + + " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');" + + "});"; + + if (fs.existsSync(scriptFile)) _unlinkSync(scriptFile); + if (fs.existsSync(stdoutFile)) _unlinkSync(stdoutFile); + if (fs.existsSync(codeFile)) _unlinkSync(codeFile); + + fs.writeFileSync(scriptFile, script); + child.exec('"'+process.execPath+'" '+scriptFile, { + env: process.env, + cwd: exports.pwd(), + maxBuffer: 20*1024*1024 + }); + + // The wait loop + // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage + // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing + // CPU usage, though apparently not so much on Windows) + while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } + while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } + + // At this point codeFile exists, but it's not necessarily flushed yet. + // Keep reading it until it is. + var code = parseInt('', 10); + while (isNaN(code)) { + code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10); + } + + var stdout = fs.readFileSync(stdoutFile, 'utf8'); + + // No biggie if we can't erase the files now -- they're in a temp dir anyway + try { _unlinkSync(scriptFile); } catch(e) {} + try { _unlinkSync(stdoutFile); } catch(e) {} + try { _unlinkSync(codeFile); } catch(e) {} + try { _unlinkSync(sleepFile); } catch(e) {} + + // True if successful, false if not + var obj = { + code: code, + output: stdout + }; + return obj; +} // execSync() + +// Expands wildcards with matching file names. For a given array of file names 'list', returns +// another array containing all file names as per ls(list[i]). +// For example: +// expand(['file*.js']) = ['file1.js', 'file2.js', ...] +// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) +function expand(list) { + var expanded = []; + list.forEach(function(listEl) { + // Wildcard present? + if (listEl.search(/\*/) > -1) { + _ls('', listEl).forEach(function(file) { + expanded.push(file); + }); + } else { + expanded.push(listEl); + } + }); + return expanded; +} + +// Cross-platform method for splitting environment PATH variables +function splitPath(p) { + if (!p) + return []; + + if (platform === 'win') + return p.split(';'); + else + return p.split(':'); +} + +// extend(target_obj, source_obj1 [, source_obj2 ...]) +// Shallow extend, e.g.: +// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3} +function extend(target) { + var sources = [].slice.call(arguments, 1); + sources.forEach(function(source) { + for (var key in source) + target[key] = source[key]; + }); + + return target; +} + +// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. +// file can be unlinked even if it's read-only, see joyent/node#3006 +function _unlinkSync(file) { + try { + fs.unlinkSync(file); + } catch(e) { + // Try to override file permission + if (e.code === 'EPERM') { + fs.chmodSync(file, '0666'); + fs.unlinkSync(file); + } else { + throw e; + } + } +} + +// Hack to determine if file has write permissions for current user +// Avoids having to check user, group, etc, but it's probably slow +function isWriteable(file) { + var writePermission = true; + try { + var __fd = fs.openSync(file, 'a'); + fs.closeSync(__fd); + } catch(e) { + writePermission = false; + } + + return writePermission; +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/.npmignore new file mode 100644 index 000000000..a1632ab58 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/.npmignore @@ -0,0 +1,2 @@ +tmp/ + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cat.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cat.js new file mode 100644 index 000000000..d0d9ddb04 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cat.js @@ -0,0 +1,57 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// save current dir +var cur = shell.pwd(); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.cat(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.cat('/adsfasdf'); // file does not exist +assert.ok(shell.error()); + +// +// Valids +// + +// simple +var result = shell.cat('resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'test1'); + +// multiple files +var result = shell.cat('resources/file2', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'test2\ntest1'); + +// multiple files, array syntax +var result = shell.cat(['resources/file2', 'resources/file1']); +assert.equal(shell.error(), null); +assert.equal(result, 'test2\ntest1'); + +var result = shell.cat('resources/file*.txt'); +assert.equal(shell.error(), null); +assert.ok(result.search('test1') > -1); // file order might be random +assert.ok(result.search('test2') > -1); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cd.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cd.js new file mode 100644 index 000000000..e6f6c387d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cd.js @@ -0,0 +1,64 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// save current dir +var cur = shell.pwd(); + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.cd(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.cd('/adsfasdf'); // dir does not exist +assert.ok(shell.error()); + +assert.equal(fs.existsSync('resources/file1'), true); // sanity check +shell.cd('resources/file1'); // file, not dir +assert.ok(shell.error()); + +// +// Valids +// + +shell.cd(cur); +shell.cd('tmp'); +assert.equal(shell.error(), null); +assert.equal(path.basename(process.cwd()), 'tmp'); + +shell.cd(cur); +shell.cd('/'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), path.resolve('/')); + +// cd + other commands + +shell.cd(cur); +shell.rm('-f', 'tmp/*'); +assert.equal(fs.existsSync('tmp/file1'), false); +shell.cd('resources'); +assert.equal(shell.error(), null); +shell.cp('file1', '../tmp'); +assert.equal(shell.error(), null); +shell.cd('../tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), true); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/chmod.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/chmod.js new file mode 100644 index 000000000..b31e25e0b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/chmod.js @@ -0,0 +1,81 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +shell.config.silent = true; + +// +// Invalids +// + +shell.chmod('blah'); // missing args +assert.ok(shell.error()); +shell.chmod('893', 'resources/chmod'); // invalid permissions - mode must be in octal +assert.ok(shell.error()); + +// +// Valids +// + +// Test files - the bitmasking is to ignore the upper bits. +shell.chmod('755', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('755', 8)); +shell.chmod('644', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); + +shell.chmod('o+x', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('007', 8), parseInt('005', 8)); +shell.chmod('644', 'resources/chmod/file1'); + +shell.chmod('+x', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('755', 8)); +shell.chmod('644', 'resources/chmod/file1'); + +// Test setuid +shell.chmod('u+s', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('4000', 8), parseInt('4000', 8)); +shell.chmod('u-s', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); + +// according to POSIX standards at http://linux.die.net/man/1/chmod, +// setuid is never cleared from a directory unless explicitly asked for. +shell.chmod('u+s', 'resources/chmod/c'); +shell.chmod('755', 'resources/chmod/c'); +assert.equal(fs.statSync('resources/chmod/c').mode & parseInt('4000', 8), parseInt('4000', 8)); +shell.chmod('u-s', 'resources/chmod/c'); + +// Test setgid +shell.chmod('g+s', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('2000', 8), parseInt('2000', 8)); +shell.chmod('g-s', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); + +// Test sticky bit +shell.chmod('+t', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('1000', 8), parseInt('1000', 8)); +shell.chmod('-t', 'resources/chmod/file1'); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); +assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('1000', 8), 0); + +// Test directories +shell.chmod('a-w', 'resources/chmod/b/a/b'); +assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('555', 8)); +shell.chmod('755', 'resources/chmod/b/a/b'); + +// Test recursion +shell.chmod('-R', 'a+w', 'resources/chmod/b'); +assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('777', 8)); +shell.chmod('-R', '755', 'resources/chmod/b'); +assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('755', 8)); + +// Test symbolic links w/ recursion - WARNING: *nix only +fs.symlinkSync('resources/chmod/b/a', 'resources/chmod/a/b/c/link', 'dir'); +shell.chmod('-R', 'u-w', 'resources/chmod/a/b'); +assert.equal(fs.statSync('resources/chmod/a/b/c').mode & parseInt('700', 8), parseInt('500', 8)); +assert.equal(fs.statSync('resources/chmod/b/a').mode & parseInt('700', 8), parseInt('700', 8)); +shell.chmod('-R', 'u+w', 'resources/chmod/a/b'); +fs.unlinkSync('resources/chmod/a/b/c/link'); + +shell.exit(123); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/config.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/config.js new file mode 100644 index 000000000..bd81ec0cb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/config.js @@ -0,0 +1,50 @@ +var shell = require('..'); + +var assert = require('assert'), + child = require('child_process'); + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// +// config.silent +// + +assert.equal(shell.config.silent, false); // default + +shell.config.silent = true; +assert.equal(shell.config.silent, true); + +shell.config.silent = false; +assert.equal(shell.config.silent, false); + +// +// config.fatal +// + +assert.equal(shell.config.fatal, false); // default + +// +// config.fatal = false +// +shell.mkdir('-p', 'tmp'); +var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); config.silent=true; config.fatal=false; cp("this_file_doesnt_exist", "."); echo("got here");'; +script.to(file); +child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout.match('got here')); + + // + // config.fatal = true + // + shell.mkdir('-p', 'tmp'); + var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); config.silent=true; config.fatal=true; cp("this_file_doesnt_exist", "."); echo("got here");'; + script.to(file); + child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(!stdout.match('got here')); + + shell.exit(123); + }); +}); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cp.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cp.js new file mode 100644 index 000000000..39b3ba9da --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/cp.js @@ -0,0 +1,143 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.cp(); +assert.ok(shell.error()); + +shell.cp('file1'); +assert.ok(shell.error()); + +shell.cp('-f'); +assert.ok(shell.error()); + +shell.rm('-rf', 'tmp/*'); +shell.cp('-@', 'resources/file1', 'tmp/file1'); // option not supported, files OK +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), false); + +shell.cp('-Z', 'asdfasdf', 'tmp/file2'); // option not supported, files NOT OK +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file2'), false); + +shell.cp('asdfasdf', 'tmp'); // source does not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/asdfasdf'), false); + +shell.cp('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 2); +assert.equal(fs.existsSync('tmp/asdfasdf1'), false); +assert.equal(fs.existsSync('tmp/asdfasdf2'), false); + +shell.cp('asdfasdf1', 'asdfasdf2', 'resources/file1'); // too many sources (dest is file) +assert.ok(shell.error()); + +shell.cp('resources/file1', 'resources/file2'); // dest already exists +assert.ok(shell.error()); + +shell.cp('resources/file1', 'resources/file2', 'tmp/a_file'); // too many sources +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/a_file'), false); + +// +// Valids +// + +// simple - to dir +shell.cp('resources/file1', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); + +// simple - to file +shell.cp('resources/file2', 'tmp/file2'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file2'), true); + +// simple - file list +shell.rm('-rf', 'tmp/*'); +shell.cp('resources/file1', 'resources/file2', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +// simple - file list, array syntax +shell.rm('-rf', 'tmp/*'); +shell.cp(['resources/file1', 'resources/file2'], 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +shell.cp('resources/file2', 'tmp/file3'); +assert.equal(fs.existsSync('tmp/file3'), true); +shell.cp('-f', 'resources/file2', 'tmp/file3'); // file exists, but -f specified +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file3'), true); + +// wildcard +shell.rm('tmp/file1', 'tmp/file2'); +shell.cp('resources/file*', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); + +//recursive, nothing exists +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(shell.ls('-R', 'resources/cp') + '', shell.ls('-R', 'tmp/cp') + ''); + +//recursive, nothing exists, source ends in '/' (see Github issue #15) +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp/', 'tmp/'); +assert.equal(shell.error(), null); +assert.equal(shell.ls('-R', 'resources/cp') + '', shell.ls('-R', 'tmp') + ''); + +//recursive, everything exists, no force flag +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp', 'tmp'); +shell.cp('-R', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); // crash test only + +//recursive, everything exists, with force flag +shell.rm('-rf', 'tmp/*'); +shell.cp('-R', 'resources/cp', 'tmp'); +'changing things around'.to('tmp/cp/dir_a/z'); +assert.notEqual(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // before cp +shell.cp('-Rf', 'resources/cp', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(shell.cat('resources/cp/dir_a/z'), shell.cat('tmp/cp/dir_a/z')); // after cp + +//recursive, creates dest dir since it's only one level deep (see Github issue #44) +shell.rm('-rf', 'tmp/*'); +shell.cp('-r', 'resources/issue44/*', 'tmp/dir2'); +assert.equal(shell.error(), null); +assert.equal(shell.ls('-R', 'resources/issue44') + '', shell.ls('-R', 'tmp/dir2') + ''); +assert.equal(shell.cat('resources/issue44/main.js'), shell.cat('tmp/dir2/main.js')); + +//recursive, does *not* create dest dir since it's too deep (see Github issue #44) +shell.rm('-rf', 'tmp/*'); +shell.cp('-r', 'resources/issue44/*', 'tmp/dir2/dir3'); +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/dir2'), false); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/dirs.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/dirs.js new file mode 100644 index 000000000..e9f11e6ca --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/dirs.js @@ -0,0 +1,37 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +var root = path.resolve(); + +shell.pushd('resources/pushd'); +shell.pushd('a'); + +var trail = [ + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]; + +assert.deepEqual(shell.dirs(), trail); + +// Single items +assert.equal(shell.dirs('+0'), trail[0]); +assert.equal(shell.dirs('+1'), trail[1]); +assert.equal(shell.dirs('+2'), trail[2]); +assert.equal(shell.dirs('-0'), trail[2]); +assert.equal(shell.dirs('-1'), trail[1]); +assert.equal(shell.dirs('-2'), trail[0]); + +// Clearing items +assert.deepEqual(shell.dirs('-c'), []); +assert(!shell.error()); + +shell.exit(123); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/echo.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/echo.js new file mode 100644 index 000000000..82faa51b1 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/echo.js @@ -0,0 +1,50 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'), + child = require('child_process'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Valids +// + + +// From here on we use child.exec() to intercept the stdout + + +// simple test with defaults +shell.mkdir('-p', 'tmp'); +var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); echo("-asdf", "111");'; // test '-' bug (see issue #20) +script.to(file); +child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout === '-asdf 111\n' || stdout === '-asdf 111\nundefined\n'); // 'undefined' for v0.4 + + // simple test with silent(true) + shell.mkdir('-p', 'tmp'); + var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../global.js\'); config.silent=true; echo(555);'; + script.to(file); + child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout === '555\n' || stdout === '555\nundefined\n'); // 'undefined' for v0.4 + + theEnd(); + }); +}); + +function theEnd() { + shell.exit(123); +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/env.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/env.js new file mode 100644 index 000000000..0e041d6ad --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/env.js @@ -0,0 +1,19 @@ +var shell = require('..'); + +var assert = require('assert'); + +shell.config.silent = true; + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Valids +// + +assert.equal(shell.env['PATH'], process.env['PATH']); + +shell.env['SHELLJS_TEST'] = 'hello world'; +assert.equal(shell.env['SHELLJS_TEST'], process.env['SHELLJS_TEST']); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/exec.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/exec.js new file mode 100644 index 000000000..e72180811 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/exec.js @@ -0,0 +1,109 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'), + util = require('util'), + child = require('child_process'); + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +// +// Invalids +// + +shell.exec(); +assert.ok(shell.error()); + +var result = shell.exec('asdfasdf'); // could not find command +assert.ok(result.code > 0); + + +// +// Valids +// + +// +// sync +// + +// check if stdout goes to output +var result = shell.exec('node -e \"console.log(1234);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 + +// check if stderr goes to output +var result = shell.exec('node -e \"console.error(1234);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n' || result.output === '1234\nundefined\n'); // 'undefined' for v0.4 + +// check if stdout + stderr go to output +var result = shell.exec('node -e \"console.error(1234); console.log(666);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.ok(result.output === '1234\n666\n' || result.output === '1234\n666\nundefined\n'); // 'undefined' for v0.4 + +// check exit code +var result = shell.exec('node -e \"process.exit(12);\"'); +assert.equal(shell.error(), null); +assert.equal(result.code, 12); + +// interaction with cd +shell.cd('resources/external'); +var result = shell.exec('node node_script.js'); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.equal(result.output, 'node_script_1234\n'); +shell.cd('../..'); + +// check quotes escaping +var result = shell.exec( util.format('node -e "console.log(%s);"', "\\\"\\'+\\'_\\'+\\'\\\"") ); +assert.equal(shell.error(), null); +assert.equal(result.code, 0); +assert.equal(result.output, "'+'_'+'\n"); + +// +// async +// + +// no callback +var c = shell.exec('node -e \"console.log(1234)\"', {async:true}); +assert.equal(shell.error(), null); +assert.ok('stdout' in c, 'async exec returns child process object'); + +// +// callback as 2nd argument +// +shell.exec('node -e \"console.log(5678);\"', function(code, output) { + assert.equal(code, 0); + assert.ok(output === '5678\n' || output === '5678\nundefined\n'); // 'undefined' for v0.4 + + // + // callback as 3rd argument + // + shell.exec('node -e \"console.log(5566);\"', {async:true}, function(code, output) { + assert.equal(code, 0); + assert.ok(output === '5566\n' || output === '5566\nundefined\n'); // 'undefined' for v0.4 + + // + // callback as 3rd argument (slient:true) + // + shell.exec('node -e \"console.log(5678);\"', {silent:true}, function(code, output) { + assert.equal(code, 0); + assert.ok(output === '5678\n' || output === '5678\nundefined\n'); // 'undefined' for v0.4 + + shell.exit(123); + + }); + + }); + +}); + +assert.equal(shell.error(), null); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/find.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/find.js new file mode 100644 index 000000000..d375f8693 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/find.js @@ -0,0 +1,56 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +var result = shell.find(); // no paths given +assert.ok(shell.error()); + +// +// Valids +// + +// current path +shell.cd('resources/find'); +var result = shell.find('.'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('.hidden') > -1, true); +assert.equal(result.indexOf('dir1/dir11/a_dir11') > -1, true); +assert.equal(result.length, 11); +shell.cd('../..'); + +// simple path +var result = shell.find('resources/find'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/.hidden') > -1, true); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.length, 11); + +// multiple paths - comma +var result = shell.find('resources/find/dir1', 'resources/find/dir2'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); +assert.equal(result.length, 6); + +// multiple paths - array +var result = shell.find(['resources/find/dir1', 'resources/find/dir2']); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); +assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); +assert.equal(result.length, 6); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/grep.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/grep.js new file mode 100644 index 000000000..71db9820a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/grep.js @@ -0,0 +1,59 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.grep(); +assert.ok(shell.error()); + +shell.grep(/asdf/g); // too few args +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.grep(/asdf/g, '/asdfasdf'); // no such file +assert.ok(shell.error()); + +// +// Valids +// + +var result = shell.grep('line', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result.split('\n').length - 1, 4); + +var result = shell.grep('-v', 'line', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result.split('\n').length - 1, 8); + +var result = shell.grep('line one', 'resources/a.txt'); +assert.equal(shell.error(), null); +assert.equal(result, 'This is line one\n'); + +// multiple files +var result = shell.grep(/test/, 'resources/file1.txt', 'resources/file2.txt'); +assert.equal(shell.error(), null); +assert.equal(result, 'test1\ntest2\n'); + +// multiple files, array syntax +var result = shell.grep(/test/, ['resources/file1.txt', 'resources/file2.txt']); +assert.equal(shell.error(), null); +assert.equal(result, 'test1\ntest2\n'); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/ls.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/ls.js new file mode 100644 index 000000000..5067b7dd9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/ls.js @@ -0,0 +1,202 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +var result = shell.ls('/asdfasdf'); // no such file or dir +assert.ok(shell.error()); +assert.equal(result.length, 0); + +// +// Valids +// + +var result = shell.ls(); +assert.equal(shell.error(), null); + +var result = shell.ls('/'); +assert.equal(shell.error(), null); + +// no args +shell.cd('resources/ls'); +var result = shell.ls(); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.length, 6); +shell.cd('../..'); + +// simple arg +var result = shell.ls('resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.length, 6); + +// no args, 'all' option +shell.cd('resources/ls'); +var result = shell.ls('-A'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('.hidden_file') > -1, true); +assert.equal(result.indexOf('.hidden_dir') > -1, true); +assert.equal(result.length, 8); +shell.cd('../..'); + +// no args, 'all' option +shell.cd('resources/ls'); +var result = shell.ls('-a'); // (deprecated) backwards compatibility test +assert.equal(shell.error(), null); +assert.equal(result.indexOf('file1') > -1, true); +assert.equal(result.indexOf('file2') > -1, true); +assert.equal(result.indexOf('file1.js') > -1, true); +assert.equal(result.indexOf('file2.js') > -1, true); +assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('.hidden_file') > -1, true); +assert.equal(result.indexOf('.hidden_dir') > -1, true); +assert.equal(result.length, 8); +shell.cd('../..'); + +// wildcard, simple +var result = shell.ls('resources/ls/*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/file1') > -1, true); +assert.equal(result.indexOf('resources/ls/file2') > -1, true); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); +assert.equal(result.length, 6); + +// wildcard, hidden only +var result = shell.ls('resources/ls/.*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/.hidden_file') > -1, true); +assert.equal(result.indexOf('resources/ls/.hidden_dir') > -1, true); +assert.equal(result.length, 2); + +// wildcard, mid-file +var result = shell.ls('resources/ls/f*le*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 5); +assert.equal(result.indexOf('resources/ls/file1') > -1, true); +assert.equal(result.indexOf('resources/ls/file2') > -1, true); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); + +// wildcard, mid-file with dot (should escape dot for regex) +var result = shell.ls('resources/ls/f*le*.js'); +assert.equal(shell.error(), null); +assert.equal(result.length, 2); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); + +// wildcard, should not do partial matches +var result = shell.ls('resources/ls/*.j'); // shouldn't get .js +assert.equal(shell.error(), null); +assert.equal(result.length, 0); + +// wildcard, all files with extension +var result = shell.ls('resources/ls/*.*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 3); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); + +// wildcard, with additional path +var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir'); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('b_dir') > -1, true); // no wildcard == no path prefix +assert.equal(result.indexOf('nada') > -1, true); // no wildcard == no path prefix + +// wildcard for both paths +var result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir/*'); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); + +// wildcard for both paths, array +var result = shell.ls(['resources/ls/f*le*.js', 'resources/ls/a_dir/*']); +assert.equal(shell.error(), null); +assert.equal(result.length, 4); +assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); +assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); + +// recursive, no path +shell.cd('resources/ls'); +var result = shell.ls('-R'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); +shell.cd('../..'); + +// recusive, path given +var result = shell.ls('-R', 'resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); + +// recusive, path given - 'all' flag +var result = shell.ls('-RA', 'resources/ls'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('a_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); +assert.equal(result.indexOf('a_dir/.hidden_dir/nada') > -1, true); +assert.equal(result.length, 14); + +// recursive, wildcard +var result = shell.ls('-R', 'resources/ls/*'); +assert.equal(shell.error(), null); +assert.equal(result.indexOf('resources/ls/a_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir') > -1, true); +assert.equal(result.indexOf('resources/ls/a_dir/b_dir/z') > -1, true); +assert.equal(result.length, 9); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/make.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/make.js new file mode 100644 index 000000000..3edbd8ce9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/make.js @@ -0,0 +1,20 @@ +var shell = require('..'), + child = require('child_process'), + assert = require('assert'); + +shell.mkdir('-p', 'tmp'); +var file = 'tmp/tempscript'+Math.random()+'.js', + script = 'require(\'../../make.js\');' + + 'target.all=function(){' + + ' echo("first"); '+ + ' cp("this_file_doesnt_exist", ".");' + + ' echo("second");' + + '}'; + +script.to(file); +child.exec('node '+file, function(err, stdout, stderr) { + assert.ok(stdout.match('first')); + assert.ok(!stdout.match('second')); // Make should die on errors, so this should never get echoed + + shell.exit(123); +}); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mkdir.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mkdir.js new file mode 100644 index 000000000..1f93422ad --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mkdir.js @@ -0,0 +1,79 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.mkdir(); +assert.ok(shell.error()); + +var mtime = fs.statSync('tmp').mtime.toString(); +shell.mkdir('tmp'); // dir already exists +assert.ok(shell.error()); +assert.equal(fs.statSync('tmp').mtime.toString(), mtime); // didn't mess with dir + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.mkdir('/asdfasdf/asdfasdf'); // root path does not exist +assert.ok(shell.error()); +assert.equal(fs.existsSync('/asdfasdf'), false); + +// +// Valids +// + +assert.equal(fs.existsSync('tmp/t1'), false); +shell.mkdir('tmp/t1'); // simple dir +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/t1'), true); + +assert.equal(fs.existsSync('tmp/t2'), false); +assert.equal(fs.existsSync('tmp/t3'), false); +shell.mkdir('tmp/t2', 'tmp/t3'); // multiple dirs +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/t2'), true); +assert.equal(fs.existsSync('tmp/t3'), true); + +assert.equal(fs.existsSync('tmp/t1'), true); +assert.equal(fs.existsSync('tmp/t4'), false); +shell.mkdir('tmp/t1', 'tmp/t4'); // one dir exists, one doesn't +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/t1'), true); +assert.equal(fs.existsSync('tmp/t4'), true); + +assert.equal(fs.existsSync('tmp/a'), false); +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', 'tmp/a'); // revert + +// multiple dirs +shell.mkdir('-p', 'tmp/zzza', 'tmp/zzzb', 'tmp/zzzc'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/zzza'), true); +assert.equal(fs.existsSync('tmp/zzzb'), true); +assert.equal(fs.existsSync('tmp/zzzc'), true); + +// multiple dirs, array syntax +shell.mkdir('-p', ['tmp/yyya', 'tmp/yyyb', 'tmp/yyyc']); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/yyya'), true); +assert.equal(fs.existsSync('tmp/yyyb'), true); +assert.equal(fs.existsSync('tmp/yyyc'), true); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mv.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mv.js new file mode 100644 index 000000000..89bca91ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/mv.js @@ -0,0 +1,130 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// Prepare tmp/ +shell.cp('resources/*', 'tmp'); + +// +// Invalids +// + +shell.mv(); +assert.ok(shell.error()); + +shell.mv('file1'); +assert.ok(shell.error()); + +shell.mv('-f'); +assert.ok(shell.error()); + +shell.mv('-Z', 'tmp/file1', 'tmp/file1'); // option not supported +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), true); + +shell.mv('asdfasdf', 'tmp'); // source does not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 1); +assert.equal(fs.existsSync('tmp/asdfasdf'), false); + +shell.mv('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist +assert.ok(shell.error()); +assert.equal(numLines(shell.error()), 2); +assert.equal(fs.existsSync('tmp/asdfasdf1'), false); +assert.equal(fs.existsSync('tmp/asdfasdf2'), false); + +shell.mv('asdfasdf1', 'asdfasdf2', 'tmp/file1'); // too many sources (dest is file) +assert.ok(shell.error()); + +shell.mv('tmp/file1', 'tmp/file2'); // dest already exists +assert.ok(shell.error()); + +shell.mv('tmp/file1', 'tmp/file2', 'tmp/a_file'); // too many sources (exist, but dest is file) +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/a_file'), false); + +shell.mv('tmp/file*', 'tmp/file1'); // can't use wildcard when dest is file +assert.ok(shell.error()); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); +assert.equal(fs.existsSync('tmp/file1.js'), true); +assert.equal(fs.existsSync('tmp/file2.js'), true); + +// +// Valids +// + +shell.cd('tmp'); + +// handles self OK +shell.mkdir('tmp2'); +shell.mv('*', 'tmp2'); // has to handle self (tmp2 --> tmp2) without throwing error +assert.ok(shell.error()); // there's an error, but not fatal +assert.equal(fs.existsSync('tmp2/file1'), true); // moved OK +shell.mv('tmp2/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); // moved OK + +shell.mv('file1', 'file3'); // one source +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file3'), true); +shell.mv('file3', 'file1'); // revert +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), true); + +// two sources +shell.rm('-rf', 't'); +shell.mkdir('-p', 't'); +shell.mv('file1', 'file2', 't'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), false); +assert.equal(fs.existsSync('t/file1'), true); +assert.equal(fs.existsSync('t/file2'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); +assert.equal(fs.existsSync('file2'), true); + +// two sources, array style +shell.rm('-rf', 't'); +shell.mkdir('-p', 't'); +shell.mv(['file1', 'file2'], 't'); // two sources +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), false); +assert.equal(fs.existsSync('t/file1'), true); +assert.equal(fs.existsSync('t/file2'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1'), true); +assert.equal(fs.existsSync('file2'), true); + +shell.mv('file*.js', 't'); // wildcard +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1.js'), false); +assert.equal(fs.existsSync('file2.js'), false); +assert.equal(fs.existsSync('t/file1.js'), true); +assert.equal(fs.existsSync('t/file2.js'), true); +shell.mv('t/*', '.'); // revert +assert.equal(fs.existsSync('file1.js'), true); +assert.equal(fs.existsSync('file2.js'), true); + +shell.mv('-f', 'file1', 'file2'); // dest exists, but -f given +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('file1'), false); +assert.equal(fs.existsSync('file2'), true); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/popd.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/popd.js new file mode 100644 index 000000000..fd795332a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/popd.js @@ -0,0 +1,118 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +var root = path.resolve(), trail; + +function reset() { + shell.dirs('-c'); + shell.cd(root); +} + +// Valid +shell.pushd('resources/pushd'); +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ root ]); + +shell.pushd('resources/pushd'); +shell.pushd('a'); +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd'), + root +]); + +shell.pushd('b'); +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd'), + root +]); + +shell.pushd('b'); +shell.pushd('c'); +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(trail.length, 1); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ root ]); + +// Valid by index +shell.pushd('resources/pushd'); +trail = shell.popd('+0'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ root ]); + +shell.pushd('resources/pushd'); +trail = shell.popd('+1'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd') ]); + +reset(); shell.pushd('resources/pushd'); +trail = shell.popd('-0'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd') ]); + +reset(); shell.pushd('resources/pushd'); +trail = shell.popd('-1'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ root ]); + + +reset(); shell.pushd('resources/pushd'); +trail = shell.popd('-n'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd') ]); + +// Invalid +trail = shell.popd(); +assert.ok(shell.error('popd: directory stack empty\n')); + +// Test that the root dir is not stored +shell.cd('resources/pushd'); +shell.pushd('b'); +trail = shell.popd(); +assert.equal(shell.error(), null); +assert.equal(trail[0], path.resolve(root, 'resources/pushd')); +assert.equal(process.cwd(), trail[0]); +shell.popd(); +assert.ok(shell.error(), null); + +shell.cd(root); + +shell.exit(123); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pushd.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pushd.js new file mode 100644 index 000000000..32089dc2c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pushd.js @@ -0,0 +1,228 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +var root = path.resolve(), trail; + +function reset() { + shell.dirs('-c'); + shell.cd(root); +} + +// Push valid directories +trail = shell.pushd('resources/pushd'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.pushd('a'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.pushd('../b'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.pushd('c'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +// Push stuff around with positive indices +trail = shell.pushd('+0'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.pushd('+1'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root, + path.resolve(root, 'resources/pushd/b/c') +]); + +trail = shell.pushd('+2'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd'), + root, + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a') +]); + +trail = shell.pushd('+3'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root, + path.resolve(root, 'resources/pushd/b/c') +]); + +trail = shell.pushd('+4'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +// Push stuff around with negative indices +trail = shell.pushd('-0'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + root, + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd') +]); + +trail = shell.pushd('-1'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root, + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b') +]); + +trail = shell.pushd('-2'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + root, + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd') +]); + +trail = shell.pushd('-3'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +trail = shell.pushd('-4'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + path.resolve(root, 'resources/pushd/b/c'), + path.resolve(root, 'resources/pushd/b'), + path.resolve(root, 'resources/pushd/a'), + path.resolve(root, 'resources/pushd'), + root +]); + +// Push without changing directory or resolving paths +reset(); trail = shell.pushd('-n', 'resources/pushd'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + root, + 'resources/pushd' +]); + +trail = shell.pushd('-n', 'resources/pushd/a'); +assert.equal(shell.error(), null); +assert.equal(process.cwd(), trail[0]); +assert.deepEqual(trail, [ + root, + 'resources/pushd/a', + 'resources/pushd' +]); + +// Push invalid directory +shell.pushd('does/not/exist'); +assert.equal(shell.error(), 'pushd: no such file or directory: ' + path.resolve('.', 'does/not/exist') + '\n'); +assert.equal(process.cwd(), trail[0]); + +// Push without arguments should swap top two directories when stack length is 2 +reset(); trail = shell.pushd('resources/pushd'); +assert.equal(shell.error(), null); +assert.equal(trail.length, 2); +assert.equal(path.relative(root, trail[0]), 'resources/pushd'); +assert.equal(trail[1], root); +assert.equal(process.cwd(), trail[0]); +trail = shell.pushd(); +assert.equal(shell.error(), null); +assert.equal(trail.length, 2); +assert.equal(trail[0], root); +assert.equal(path.relative(root, trail[1]), 'resources/pushd'); +assert.equal(process.cwd(), trail[0]); + +// Push without arguments should swap top two directories when stack length is > 2 +trail = shell.pushd('resources/pushd/a'); +assert.equal(shell.error(), null); +assert.equal(trail.length, 3); +assert.equal(path.relative(root, trail[0]), 'resources/pushd/a'); +assert.equal(trail[1], root); +assert.equal(path.relative(root, trail[2]), 'resources/pushd'); +assert.equal(process.cwd(), trail[0]); + +trail = shell.pushd(); +assert.equal(shell.error(), null); +assert.equal(trail.length, 3); +assert.equal(trail[0], root); +assert.equal(path.relative(root, trail[1]), 'resources/pushd/a'); +assert.equal(path.relative(root, trail[2]), 'resources/pushd'); +assert.equal(process.cwd(), trail[0]); + +// Push without arguments invalid when stack is empty +reset(); shell.pushd(); +assert.equal(shell.error(), 'pushd: no other directory\n'); + +shell.exit(123); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pwd.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pwd.js new file mode 100644 index 000000000..d1f563f97 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/pwd.js @@ -0,0 +1,28 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'); + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Valids +// + +var _pwd = shell.pwd(); +assert.equal(shell.error(), null); +assert.equal(_pwd, path.resolve('.')); + +shell.cd('tmp'); +var _pwd = shell.pwd(); +assert.equal(shell.error(), null); +assert.equal(path.basename(_pwd), 'tmp'); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/a.txt b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/a.txt new file mode 100644 index 000000000..356ce4912 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/a.txt @@ -0,0 +1,11 @@ +This is line one +This is line two + +This is line four +. +. +More content here +. +. + +This is line eleven diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/a/b/c/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/a/b/c/.npmignore new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/b/a/b/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/b/a/b/.npmignore new file mode 100755 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/c/a/b/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/c/a/b/.npmignore new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/file1 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/file1 new file mode 100644 index 000000000..db3f9ca6e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/chmod/file1 @@ -0,0 +1,2 @@ +this is test file 1 +default state should be 0644 (rw-r--r--) diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/a b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/a new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/a @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/b b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/b new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/b @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_a/z b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_a/z new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_a/z @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/external/node_script.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/external/node_script.js new file mode 100755 index 000000000..3b2d24a06 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/external/node_script.js @@ -0,0 +1,2 @@ +console.log('node_script_1234'); + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1 new file mode 100644 index 000000000..f079749c4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1 @@ -0,0 +1 @@ +test1 \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.js new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.js @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.txt b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.txt new file mode 100644 index 000000000..a5bce3fd2 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file1.txt @@ -0,0 +1 @@ +test1 diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2 new file mode 100644 index 000000000..d606037cb --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2 @@ -0,0 +1 @@ +test2 \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.js new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.js @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.txt b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.txt new file mode 100644 index 000000000..180cf8328 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/file2.txt @@ -0,0 +1 @@ +test2 diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/.hidden b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/.hidden new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/.hidden @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/a b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/a new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/a @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/b b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/b new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/b @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/a_dir1 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/a_dir1 new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/a_dir1 @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir1/dir11/a_dir11 @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir2/a_dir1 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir2/a_dir1 new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/find/dir2/a_dir1 @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/issue44/main.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/issue44/main.js new file mode 100644 index 000000000..d800886d9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/issue44/main.js @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_dir/nada b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_dir/nada new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_dir/nada @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_file b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_file new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/.hidden_file @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada new file mode 100644 index 000000000..5fedf5729 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/.hidden_dir/nada @@ -0,0 +1 @@ +nada \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/b_dir/z @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/nada b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/nada new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/a_dir/nada @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1 new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1 @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1.js new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file1.js @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2 b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2 new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2 @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2.js new file mode 100644 index 000000000..9daeafb98 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/file2.js @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped new file mode 100644 index 000000000..8bd6648ed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/ls/filename(with)[chars$]^that.must+be-escaped @@ -0,0 +1 @@ +asdf diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/a/dummy b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/a/dummy new file mode 100644 index 000000000..72e12a968 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/a/dummy @@ -0,0 +1 @@ +meh \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/b/c/dummy b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/b/c/dummy new file mode 100644 index 000000000..72e12a968 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/resources/pushd/b/c/dummy @@ -0,0 +1 @@ +meh \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/rm.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/rm.js new file mode 100644 index 000000000..61182a112 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/rm.js @@ -0,0 +1,183 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.rm(); +assert.ok(shell.error()); + +shell.rm('asdfasdf'); // file does not exist +assert.ok(shell.error()); + +shell.rm('-f'); // no file +assert.ok(shell.error()); + +shell.rm('-@', 'resources/file1'); // invalid option +assert.ok(shell.error()); +assert.equal(fs.existsSync('resources/file1'), true); + +// +// Valids +// + +// file does not exist, but -f specified +shell.rm('-f', 'asdfasdf'); +assert.equal(shell.error(), null); + +// simple rm +shell.cp('-f', 'resources/file1', 'tmp/file1'); +assert.equal(fs.existsSync('tmp/file1'), true); +shell.rm('tmp/file1'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), false); + +// recursive dir removal - small-caps '-r' +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-rf', 'tmp/a'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// recursive dir removal - capital '-R' +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', 'tmp/a'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// recursive dir removal - absolute path +shell.mkdir('-p', 'tmp/a/b/c'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +shell.rm('-Rf', path.resolve('./tmp/a')); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/a'), false); + +// wildcard +shell.cp('-f', 'resources/file*', 'tmp'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), true); +assert.equal(fs.existsSync('tmp/file2'), true); +assert.equal(fs.existsSync('tmp/file1.js'), true); +assert.equal(fs.existsSync('tmp/file2.js'), true); +shell.rm('tmp/file*'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync('tmp/file1'), false); +assert.equal(fs.existsSync('tmp/file2'), false); +assert.equal(fs.existsSync('tmp/file1.js'), false); +assert.equal(fs.existsSync('tmp/file2.js'), false); + +// recursive dir removal +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', 'tmp/*'); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 1); +assert.equal(contents[0], '.hidden'); // shouldn't remove hiddden if no .* given + +// recursive dir removal +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', 'tmp/*', 'tmp/.*'); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 0); + +// recursive dir removal - array-syntax +shell.mkdir('-p', 'tmp/a/b/c'); +shell.mkdir('-p', 'tmp/b'); +shell.mkdir('-p', 'tmp/c'); +shell.mkdir('-p', 'tmp/.hidden'); +assert.equal(fs.existsSync('tmp/a/b/c'), true); +assert.equal(fs.existsSync('tmp/b'), true); +assert.equal(fs.existsSync('tmp/c'), true); +assert.equal(fs.existsSync('tmp/.hidden'), true); +shell.rm('-rf', ['tmp/*', 'tmp/.*']); +assert.equal(shell.error(), null); +var contents = fs.readdirSync('tmp'); +assert.equal(contents.length, 0); + +// removal of a read-only file (unforced) +shell.mkdir('-p', 'tmp/readonly'); +'asdf'.to('tmp/readonly/file1'); +fs.chmodSync('tmp/readonly/file1', '0444'); // -r--r--r-- +shell.rm('tmp/readonly/file1'); +assert.equal(fs.existsSync('tmp/readonly/file1'), true); // bash's rm always asks before removing read-only files + // here we just assume "no" + +// removal of a read-only file (forced) +shell.mkdir('-p', 'tmp/readonly'); +'asdf'.to('tmp/readonly/file2'); +fs.chmodSync('tmp/readonly/file2', '0444'); // -r--r--r-- +shell.rm('-f', 'tmp/readonly/file2'); +assert.equal(fs.existsSync('tmp/readonly/file2'), false); + +// removal of a tree containing read-only files (unforced) +shell.mkdir('-p', 'tmp/tree2'); +'asdf'.to('tmp/tree2/file1'); +'asdf'.to('tmp/tree2/file2'); +fs.chmodSync('tmp/tree2/file1', '0444'); // -r--r--r-- +shell.rm('-r', 'tmp/tree2'); +assert.equal(fs.existsSync('tmp/tree2/file1'), true); +assert.equal(fs.existsSync('tmp/tree2/file2'), false); + +// removal of a tree containing read-only files (forced) +shell.mkdir('-p', 'tmp/tree'); +'asdf'.to('tmp/tree/file1'); +'asdf'.to('tmp/tree/file2'); +fs.chmodSync('tmp/tree/file1', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree'); +assert.equal(fs.existsSync('tmp/tree'), false); + +// removal of a sub-tree containing read-only and hidden files - rm('dir/*') +shell.mkdir('-p', 'tmp/tree3'); +shell.mkdir('-p', 'tmp/tree3/subtree'); +shell.mkdir('-p', 'tmp/tree3/.hidden'); +'asdf'.to('tmp/tree3/subtree/file'); +'asdf'.to('tmp/tree3/.hidden/file'); +'asdf'.to('tmp/tree3/file'); +fs.chmodSync('tmp/tree3/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree3/subtree/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree3/.hidden/file', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree3/*', 'tmp/tree3/.*'); // erase dir contents +assert.equal(shell.ls('tmp/tree3').length, 0); + +// removal of a sub-tree containing read-only and hidden files - rm('dir') +shell.mkdir('-p', 'tmp/tree4'); +shell.mkdir('-p', 'tmp/tree4/subtree'); +shell.mkdir('-p', 'tmp/tree4/.hidden'); +'asdf'.to('tmp/tree4/subtree/file'); +'asdf'.to('tmp/tree4/.hidden/file'); +'asdf'.to('tmp/tree4/file'); +fs.chmodSync('tmp/tree4/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree4/subtree/file', '0444'); // -r--r--r-- +fs.chmodSync('tmp/tree4/.hidden/file', '0444'); // -r--r--r-- +shell.rm('-rf', 'tmp/tree4'); // erase dir contents +assert.equal(fs.existsSync('tmp/tree4'), false); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/sed.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/sed.js new file mode 100644 index 000000000..d3d66b116 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/sed.js @@ -0,0 +1,58 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.sed(); +assert.ok(shell.error()); + +shell.sed(/asdf/g); // too few args +assert.ok(shell.error()); + +shell.sed(/asdf/g, 'nada'); // too few args +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +shell.sed(/asdf/g, 'nada', '/asdfasdf'); // no such file +assert.ok(shell.error()); + +// +// Valids +// + +shell.cp('-f', 'resources/file1', 'tmp/file1'); +var result = shell.sed('test1', 'hello', 'tmp/file1'); // search string +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); + +var result = shell.sed(/test1/, 'hello', 'tmp/file1'); // search regex +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); + +var result = shell.sed(/test1/, 1234, 'tmp/file1'); // numeric replacement +assert.equal(shell.error(), null); +assert.equal(result, '1234'); + +var result = shell.sed('-i', /test1/, 'hello', 'tmp/file1'); +assert.equal(shell.error(), null); +assert.equal(result, 'hello'); +assert.equal(shell.cat('tmp/file1'), 'hello'); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/tempdir.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/tempdir.js new file mode 100644 index 000000000..704ca5611 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/tempdir.js @@ -0,0 +1,27 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Valids +// + +var tmp = shell.tempdir(); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync(tmp), true); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/test.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/test.js new file mode 100644 index 000000000..a824edb32 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/test.js @@ -0,0 +1,91 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +var result = shell.test(); // no expression given +assert.ok(shell.error()); + +var result = shell.test('asdf'); // bad expression +assert.ok(shell.error()); + +var result = shell.test('f', 'resources/file1'); // bad expression +assert.ok(shell.error()); + +var result = shell.test('-f'); // no file +assert.ok(shell.error()); + +// +// Valids +// + +//exists +var result = shell.test('-e', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-e', 'resources/404'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//directory +var result = shell.test('-d', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-f', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-L', 'resources'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//file +var result = shell.test('-d', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-f', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/file1'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +//link +var result = shell.test('-d', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, false); + +var result = shell.test('-f', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/link'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/badlink'); +assert.equal(shell.error(), null); +assert.equal(result, true);//true + +var result = shell.test('-L', 'resources/404'); +assert.equal(shell.error(), null); +assert.equal(result, false);//false + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/to.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/to.js new file mode 100644 index 000000000..2e1253dbe --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/to.js @@ -0,0 +1,39 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +'hello world'.to(); +assert.ok(shell.error()); + +assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check +'hello world'.to('/asdfasdf/file'); +assert.ok(shell.error()); + +// +// Valids +// + +'hello world'.to('tmp/to1'); +var result = shell.cat('tmp/to1'); +assert.equal(shell.error(), null); +assert.equal(result, 'hello world'); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/which.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/which.js new file mode 100644 index 000000000..ac9a04d50 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/shelljs/test/which.js @@ -0,0 +1,38 @@ +var shell = require('..'); + +var assert = require('assert'), + path = require('path'), + fs = require('fs'); + +// Node shims for < v0.7 +fs.existsSync = fs.existsSync || path.existsSync; + +shell.config.silent = true; + +function numLines(str) { + return typeof str === 'string' ? str.match(/\n/g).length : 0; +} + +shell.rm('-rf', 'tmp'); +shell.mkdir('tmp'); + +// +// Invalids +// + +shell.which(); +assert.ok(shell.error()); + +var result = shell.which('asdfasdfasdfasdfasdf'); // what are the odds... +assert.equal(shell.error(), null); +assert.equal(result, null); + +// +// Valids +// + +var result = shell.which('node'); +assert.equal(shell.error(), null); +assert.equal(fs.existsSync(result), true); + +shell.exit(123); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.npmignore b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.npmignore new file mode 100644 index 000000000..4e5886dea --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.npmignore @@ -0,0 +1,4 @@ +test/ +Rakefile +docs/ +raw/ diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.travis.yml b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.travis.yml new file mode 100644 index 000000000..99dc7712c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 +notifications: + email: false diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CNAME b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CNAME new file mode 100644 index 000000000..a007e65c4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CNAME @@ -0,0 +1 @@ +underscorejs.org diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CONTRIBUTING.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CONTRIBUTING.md new file mode 100644 index 000000000..de5d5626f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/CONTRIBUTING.md @@ -0,0 +1,9 @@ +## How to contribute to Underscore.js + +* Before you open a ticket or send a pull request, [search](https://github.com/documentcloud/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. + +* Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/). + +* Use the same coding style as the rest of the [codebase](https://github.com/documentcloud/underscore/blob/master/underscore.js). + +* In your pull request, do not add documentation or re-build the minified `underscore-min.js` file. We'll do those things before cutting a new release. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/LICENSE b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/LICENSE new file mode 100644 index 000000000..0d8dbe40b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/README.md b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/README.md new file mode 100644 index 000000000..b1f3e50a8 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/README.md @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ + /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ + \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore.js is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://underscorejs.org + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/favicon.ico b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/favicon.ico new file mode 100644 index 000000000..030496838 Binary files /dev/null and b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/favicon.ico differ diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.html b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.html new file mode 100644 index 000000000..8c5793ab4 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.html @@ -0,0 +1,2467 @@ + + + + + + + + + Underscore.js + + + + + + +
+ +

+ +

+ +

+ Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux, + and Backbone.js's suspenders. +

+ +

+ Underscore provides 80-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

+ +

+ A complete Test & Benchmark Suite + is included for your perusal. +

+ +

+ You may also read through the annotated source code. +

+ +

+ The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

+ +

+ Underscore is an open-source component of DocumentCloud. +

+ +

Downloads (Right-click, and use "Save As")

+ + + + + + + + + + + + + + + + + +
Development Version (1.4.4)40kb, Uncompressed with Plentiful Comments
Production Version (1.4.4)4kb, Minified and Gzipped
Edge VersionUnreleased, current master, use at your own risk
+ +
+ +

Collection Functions (Arrays or Objects)

+ +

+ each_.each(list, iterator, [context]) + Alias: forEach +
+ Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

+
+_.each([1, 2, 3], alert);
+=> alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, alert);
+=> alerts each number value in turn...
+ +

+ map_.map(list, iterator, [context]) + Alias: collect +
+ Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

+
+_.map([1, 2, 3], function(num){ return num * 3; });
+=> [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=> [3, 6, 9]
+ +

+ reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
+ Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. The iterator is passed four arguments: the memo, + then the value and index (or key) of the iteration, + and finally a reference to the entire list. +

+
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=> 6
+
+ +

+ reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
+ The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

+
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=> [4, 5, 2, 3, 0, 1]
+
+ +

+ find_.find(list, iterator, [context]) + Alias: detect +
+ Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

+
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> 2
+
+ +

+ filter_.filter(list, iterator, [context]) + Alias: select +
+ Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

+
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [2, 4, 6]
+
+ +

+ where_.where(list, properties) +
+ Looks through each value in the list, returning an array of all + the values that contain all of the key-value pairs listed in properties. +

+
+_.where(listOfPlays, {author: "Shakespeare", year: 1611});
+=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
+    {title: "The Tempest", author: "Shakespeare", year: 1611}]
+
+ +

+ findWhere_.findWhere(list, properties) +
+ Looks through the list and returns the first value that matches + all of the key-value pairs listed in properties. +

+
+_.findWhere(publicServicePulitzers, {newsroom: "The New York Times"});
+=> {year: 1918, newsroom: "The New York Times",
+  reason: "For its public service in publishing in full so many official reports,
+  documents and speeches by European statesmen relating to the progress and
+  conduct of the war."}
+
+ +

+ reject_.reject(list, iterator, [context]) +
+ Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

+
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [1, 3, 5]
+
+ +

+ every_.every(list, iterator, [context]) + Alias: all +
+ Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

+
+_.every([true, 1, null, 'yes'], _.identity);
+=> false
+
+ +

+ some_.some(list, [iterator], [context]) + Alias: any +
+ Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

+
+_.some([null, 0, 'yes', false]);
+=> true
+
+ +

+ contains_.contains(list, value) + Alias: include +
+ Returns true if the value is present in the list. + Uses indexOf internally, if list is an Array. +

+
+_.contains([1, 2, 3], 3);
+=> true
+
+ +

+ invoke_.invoke(list, methodName, [*arguments]) +
+ Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

+
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=> [[1, 5, 7], [1, 2, 3]]
+
+ +

+ pluck_.pluck(list, propertyName) +
+ A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=> ["moe", "larry", "curly"]
+
+ +

+ max_.max(list, [iterator], [context]) +
+ Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=> {name : 'curly', age : 60};
+
+ +

+ min_.min(list, [iterator], [context]) +
+ Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=> 2
+
+ +

+ sortBy_.sortBy(list, iterator, [context]) +
+ Returns a sorted copy of list, ranked in ascending order by the + results of running each value through iterator. Iterator may + also be the string name of the property to sort by (eg. length). +

+
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=> [5, 4, 6, 3, 1, 2]
+
+ +

+ groupBy_.groupBy(list, iterator, [context]) +
+ Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

+
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=> {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=> {3: ["one", "two"], 5: ["three"]}
+
+ +

+ countBy_.countBy(list, iterator, [context]) +
+ Sorts a list into groups and returns a count for the number of objects + in each group. + Similar to groupBy, but instead of returning a list of values, + returns a count for the number of values in that group. +

+
+_.countBy([1, 2, 3, 4, 5], function(num) {
+  return num % 2 == 0 ? 'even' : 'odd';
+});
+=> {odd: 3, even: 2}
+
+ +

+ shuffle_.shuffle(list) +
+ Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

+
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=> [4, 1, 6, 3, 5, 2]
+
+ +

+ toArray_.toArray(list) +
+ Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

+
+(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+=> [2, 3, 4]
+
+ +

+ size_.size(list) +
+ Return the number of values in the list. +

+
+_.size({one : 1, two : 2, three : 3});
+=> 3
+
+ +

Array Functions

+ +

+ + Note: All array functions will also work on the arguments object. + However, Underscore functions are not designed to work on "sparse" arrays. + +

+ +

+ first_.first(array, [n]) + Alias: head, take +
+ Returns the first element of an array. Passing n will + return the first n elements of the array. +

+
+_.first([5, 4, 3, 2, 1]);
+=> 5
+
+ +

+ initial_.initial(array, [n]) +
+ Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

+
+_.initial([5, 4, 3, 2, 1]);
+=> [5, 4, 3, 2]
+
+ +

+ last_.last(array, [n]) +
+ Returns the last element of an array. Passing n will return + the last n elements of the array. +

+
+_.last([5, 4, 3, 2, 1]);
+=> 1
+
+ +

+ rest_.rest(array, [index]) + Alias: tail, drop +
+ Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

+
+_.rest([5, 4, 3, 2, 1]);
+=> [4, 3, 2, 1]
+
+ +

+ compact_.compact(array) +
+ Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

+
+_.compact([0, 1, false, 2, '', 3]);
+=> [1, 2, 3]
+
+ +

+ flatten_.flatten(array, [shallow]) +
+ Flattens a nested array (the nesting can be to any depth). If you + pass shallow, the array will only be flattened a single level. +

+
+_.flatten([1, [2], [3, [[4]]]]);
+=> [1, 2, 3, 4];
+
+_.flatten([1, [2], [3, [[4]]]], true);
+=> [1, 2, 3, [[4]]];
+
+ +

+ without_.without(array, [*values]) +
+ Returns a copy of the array with all instances of the values + removed. +

+
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=> [2, 3, 4]
+
+ +

+ union_.union(*arrays) +
+ Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

+
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2, 3, 101, 10]
+
+ +

+ intersection_.intersection(*arrays) +
+ Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

+
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2]
+
+ +

+ difference_.difference(array, *others) +
+ Similar to without, but returns the values from array that + are not present in the other arrays. +

+
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=> [1, 3, 4]
+
+ +

+ uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
+ Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

+
+_.uniq([1, 2, 1, 3, 1, 4]);
+=> [1, 2, 3, 4]
+
+ +

+ zip_.zip(*arrays) +
+ Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

+
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+
+ +

+ object_.object(list, [values]) +
+ Converts arrays into objects. Pass either a single list of + [key, value] pairs, or a list of keys, and a list of values. +

+
+_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
+=> {moe: 30, larry: 40, curly: 50}
+
+_.object([['moe', 30], ['larry', 40], ['curly', 50]]);
+=> {moe: 30, larry: 40, curly: 50}
+
+ +

+ indexOf_.indexOf(array, value, [isSorted]) +
+ Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search ... or, pass a number as + the third argument in order to look for the first matching value in the + array after the given index. +

+
+_.indexOf([1, 2, 3], 2);
+=> 1
+
+ +

+ lastIndexOf_.lastIndexOf(array, value, [fromIndex]) +
+ Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. Pass fromIndex to start your search at a + given index. +

+
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=> 4
+
+ +

+ sortedIndex_.sortedIndex(list, value, [iterator], [context]) +
+ Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value, including the value you pass. +

+
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=> 3
+
+ +

+ range_.range([start], stop, [step]) +
+ A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

+
+_.range(10);
+=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=> [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=> []
+
+ +

Function (uh, ahem) Functions

+ +

+ bind_.bind(function, object, [*arguments]) +
+ Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, pass arguments to the function to pre-fill them, + also known as partial application. +

+
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=> 'hi: moe'
+
+ +

+ bindAll_.bindAll(object, [*methodNames]) +
+ Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

+
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=> When the button is clicked, this.label will have the correct value...
+
+ +

+ partial_.partial(function, [*arguments]) +
+ Partially apply a function by filling in any number of its arguments, + without changing its dynamic this value. A close cousin + of bind. +

+
+var add = function(a, b) { return a + b; };
+add5 = _.partial(add, 5);
+add5(10);
+=> 15
+
+ +

+ memoize_.memoize(function, [hashFunction]) +
+ Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

+
+var fibonacci = _.memoize(function(n) {
+  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+
+ +

+ delay_.delay(function, wait, [*arguments]) +
+ Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

+
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=> 'logged later' // Appears after one second.
+
+ +

+ defer_.defer(function, [*arguments]) +
+ Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

+
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+
+ +

+ throttle_.throttle(function, wait) +
+ Creates and returns a new, throttled version of the passed function, + that, when invoked repeatedly, will only actually call the original function + at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

+
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+
+ +

+ debounce_.debounce(function, wait, [immediate]) +
+ Creates and returns a new debounced version of the passed function that + will postpone its execution until after + wait milliseconds have elapsed since the last time it + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized, and so on. +

+ +

+ Pass true for the immediate parameter to cause + debounce to trigger the function on the leading instead of the + trailing edge of the wait interval. Useful in circumstances like + preventing accidental double-clicks on a "submit" button from firing a + second time. +

+ +
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+
+ +

+ once_.once(function) +
+ Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

+
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+
+ +

+ after_.after(count, function) +
+ Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

+
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes});
+});
+// renderNotes is run once, after all notes have saved.
+
+ +

+ wrap_.wrap(function, wrapper) +
+ Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

+
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=> 'before, hello: moe, after'
+
+ +

+ compose_.compose(*functions) +
+ Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

+
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=> 'hi: moe!'
+
+ +

Object Functions

+ +

+ keys_.keys(object) +
+ Retrieve all the names of the object's properties. +

+
+_.keys({one : 1, two : 2, three : 3});
+=> ["one", "two", "three"]
+
+ +

+ values_.values(object) +
+ Return all of the values of the object's properties. +

+
+_.values({one : 1, two : 2, three : 3});
+=> [1, 2, 3]
+
+ +

+ pairs_.pairs(object) +
+ Convert an object into a list of [key, value] pairs. +

+
+_.pairs({one: 1, two: 2, three: 3});
+=> [["one", 1], ["two", 2], ["three", 3]]
+
+ +

+ invert_.invert(object) +
+ Returns a copy of the object where the keys have become the values + and the values the keys. For this to work, all of your object's values + should be unique and string serializable. +

+
+_.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"});
+=> {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};
+
+ +

+ functions_.functions(object) + Alias: methods +
+ Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

+
+_.functions(_);
+=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+
+ +

+ extend_.extend(destination, *sources) +
+ Copy all of the properties in the source objects over to the + destination object, and return the destination object. + It's in-order, so the last source will override properties of the same + name in previous arguments. +

+
+_.extend({name : 'moe'}, {age : 50});
+=> {name : 'moe', age : 50}
+
+ +

+ pick_.pick(object, *keys) +
+ Return a copy of the object, filtered to only have values for + the whitelisted keys (or array of valid keys). +

+
+_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
+=> {name : 'moe', age : 50}
+
+ +

+ omit_.omit(object, *keys) +
+ Return a copy of the object, filtered to omit the blacklisted + keys (or array of keys). +

+
+_.omit({name : 'moe', age : 50, userid : 'moe1'}, 'userid');
+=> {name : 'moe', age : 50}
+
+ +

+ defaults_.defaults(object, *defaults) +
+ Fill in null and undefined properties in object with values from the + defaults objects, and return the object. As soon as the + property is filled, further defaults will have no effect. +

+
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=> {flavor : "chocolate", sprinkles : "lots"}
+
+ +

+ clone_.clone(object) +
+ Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

+
+_.clone({name : 'moe'});
+=> {name : 'moe'};
+
+ +

+ tap_.tap(object, interceptor) +
+ Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

+
+_.chain([1,2,3,200])
+  .filter(function(num) { return num % 2 == 0; })
+  .tap(alert)
+  .map(function(num) { return num * num })
+  .value();
+=> // [2, 200] (alerted)
+=> [4, 40000]
+
+ +

+ has_.has(object, key) +
+ Does the object contain the given key? Identical to + object.hasOwnProperty(key), but uses a safe reference to the + hasOwnProperty function, in case it's been + overridden accidentally. +

+
+_.has({a: 1, b: 2, c: 3}, "b");
+=> true
+
+ +

+ isEqual_.isEqual(object, other) +
+ Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

+
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=> false
+_.isEqual(moe, clone);
+=> true
+
+ +

+ isEmpty_.isEmpty(object) +
+ Returns true if object contains no values. +

+
+_.isEmpty([1, 2, 3]);
+=> false
+_.isEmpty({});
+=> true
+
+ +

+ isElement_.isElement(object) +
+ Returns true if object is a DOM element. +

+
+_.isElement(jQuery('body')[0]);
+=> true
+
+ +

+ isArray_.isArray(object) +
+ Returns true if object is an Array. +

+
+(function(){ return _.isArray(arguments); })();
+=> false
+_.isArray([1,2,3]);
+=> true
+
+ +

+ isObject_.isObject(value) +
+ Returns true if value is an Object. Note that JavaScript + arrays and functions are objects, while (normal) strings and numbers are not. +

+
+_.isObject({});
+=> true
+_.isObject(1);
+=> false
+
+ +

+ isArguments_.isArguments(object) +
+ Returns true if object is an Arguments object. +

+
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=> true
+_.isArguments([1,2,3]);
+=> false
+
+ +

+ isFunction_.isFunction(object) +
+ Returns true if object is a Function. +

+
+_.isFunction(alert);
+=> true
+
+ +

+ isString_.isString(object) +
+ Returns true if object is a String. +

+
+_.isString("moe");
+=> true
+
+ +

+ isNumber_.isNumber(object) +
+ Returns true if object is a Number (including NaN). +

+
+_.isNumber(8.4 * 5);
+=> true
+
+ +

+ isFinite_.isFinite(object) +
+ Returns true if object is a finite Number. +

+
+_.isFinite(-101);
+=> true
+
+_.isFinite(-Infinity);
+=> false
+
+ +

+ isBoolean_.isBoolean(object) +
+ Returns true if object is either true or false. +

+
+_.isBoolean(null);
+=> false
+
+ +

+ isDate_.isDate(object) +
+ Returns true if object is a Date. +

+
+_.isDate(new Date());
+=> true
+
+ +

+ isRegExp_.isRegExp(object) +
+ Returns true if object is a RegExp. +

+
+_.isRegExp(/moe/);
+=> true
+
+ +

+ isNaN_.isNaN(object) +
+ Returns true if object is NaN.
Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

+
+_.isNaN(NaN);
+=> true
+isNaN(undefined);
+=> true
+_.isNaN(undefined);
+=> false
+
+ +

+ isNull_.isNull(object) +
+ Returns true if the value of object is null. +

+
+_.isNull(null);
+=> true
+_.isNull(undefined);
+=> false
+
+ +

+ isUndefined_.isUndefined(value) +
+ Returns true if value is undefined. +

+
+_.isUndefined(window.missingVariable);
+=> true
+
+ +

Utility Functions

+ +

+ noConflict_.noConflict() +
+ Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

+
+var underscore = _.noConflict();
+ +

+ identity_.identity(value) +
+ Returns the same value that is used as the argument. In math: + f(x) = x
+ This function looks useless, but is used throughout Underscore as + a default iterator. +

+
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=> true
+ +

+ times_.times(n, iterator, [context]) +
+ Invokes the given iterator function n times. Each invocation of + iterator is called with an index argument. +
+ Note: this example uses the chaining syntax. +

+
+_(3).times(function(n){ genie.grantWishNumber(n); });
+ +

+ random_.random(min, max) +
+ Returns a random integer between min and max, inclusive. + If you only pass one argument, it will return a number between 0 + and that number. +

+
+_.random(0, 100);
+=> 42
+ +

+ mixin_.mixin(object) +
+ Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

+
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=> "Fabio"
+
+ +

+ uniqueId_.uniqueId([prefix]) +
+ Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. +

+
+_.uniqueId('contact_');
+=> 'contact_104'
+ +

+ escape_.escape(string) +
+ Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

+
+_.escape('Curly, Larry & Moe');
+=> "Curly, Larry &amp; Moe"
+ +

+ unescape_.unescape(string) +
+ The opposite of escape, replaces + &amp;, &lt;, &gt;, + &quot;, &#x27;, and &#x2F; + with their unescaped counterparts. +

+
+_.unescape('Curly, Larry &amp; Moe');
+=> "Curly, Larry & Moe"
+ +

+ result_.result(object, property) +
+ If the value of the named property is a function then invoke it; otherwise, return it. +

+
+var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
+_.result(object, 'cheese');
+=> "crumpets"
+_.result(object, 'stuff');
+=> "nonsense"
+ +

+ template_.template(templateString, [data], [settings]) +
+ Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using + <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + data object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the data + object as the second parameter to template in order to render + immediately instead of returning a template function. The settings argument + should be a hash containing any _.templateSettings that should be overridden. +

+ +
+var compiled = _.template("hello: <%= name %>");
+compiled({name : 'moe'});
+=> "hello: moe"
+
+var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=> "<li>moe</li><li>curly</li><li>larry</li>"
+
+var template = _.template("<b><%- value %></b>");
+template({value : '<script>'});
+=> "<b>&lt;script&gt;</b>"
+ +

+ You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

+ +
+var compiled = _.template("<% print('Hello ' + epithet); %>");
+compiled({epithet: "stooge"});
+=> "Hello stooge."
+ +

+ If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex to match expressions that should be + interpolated verbatim, an escape regex to match expressions that should + be inserted after being HTML escaped, and an evaluate regex to match + expressions that should be evaluated without insertion into the resulting + string. You may define or omit any combination of the three. + For example, to perform + Mustache.js + style templating: +

+ +
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=> "Hello Mustache!"
+ +

+ By default, template places the values from your data in the local scope + via the with statement. However, you can specify a single variable name + with the variable setting. This can significantly improve the speed + at which a template is able to render. +

+ +
+_.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
+=> "Using 'with': no"
+ +

+ Precompiling your templates can be a big help when debugging errors you can't + reproduce. This is because precompiled templates can provide line numbers and + a stack trace, something that is not possible when compiling templates on the client. + The source property is available on the compiled template + function for easy precompilation. +

+ +
<script>
+  JST.project = <%= _.template(jstText).source %>;
+</script>
+ + +

Chaining

+ +

+ You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

+ +
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });
+ +

+ Calling chain will cause all future method calls to return + wrapped objects. When you've finished the computation, use + value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

+ +
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_.chain(lyrics)
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+  }, {})
+  .value();
+
+=> {lumberjack : 2, all : 4, night : 2 ... }
+ +

+ In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

+ +

+ chain_.chain(obj) +
+ Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. +

+
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _.chain(stooges)
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=> "moe is 21"
+
+ +

+ value_(obj).value() +
+ Extracts the value of a wrapped object. +

+
+_([1, 2, 3]).value();
+=> [1, 2, 3]
+
+ + + +

+ The Underscore documentation is also available in + Simplified Chinese. +

+ +

+ Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + (source) +

+ +

+ Underscore.m, an Objective-C port + of many of the Underscore.js functions, using a syntax that encourages + chaining. + (source) +

+ +

+ _.m, an alternative + Objective-C port that tries to stick a little closer to the original + Underscore.js API. + (source) +

+ +

+ Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + (source) +

+ +

+ Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays. + (source) +

+ +

+ Underscore.cfc, + a Coldfusion port of many of the Underscore.js functions. + (source) +

+ +

+ Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

+ +

+ Ruby's Enumerable module. +

+ +

+ Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

+ +

+ Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

+ +

+ Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

+ +

+ Python's itertools. +

+ +

Change Log

+ +

+ 1.4.4Jan. 30, 2013Diff
+

    +
  • + Added _.findWhere, for finding the first element in a list + that matches a particular set of keys and values. +
  • +
  • + Added _.partial, for partially applying a function without + changing its dynamic reference to this. +
  • +
  • + Simplified bind by removing some edge cases involving + constructor functions. In short: don't _.bind your + constructors. +
  • +
  • + A minor optimization to invoke. +
  • +
  • + Fix bug in the minified version due to the minifier incorrectly + optimizing-away isFunction. +
  • +
+

+ +

+ 1.4.3Dec. 4, 2012Diff
+

    +
  • + Improved Underscore compatibility with Adobe's JS engine that can be + used to script Illustrator, Photoshop, and friends. +
  • +
  • + Added a default _.identity iterator to countBy and + groupBy. +
  • +
  • + The uniq function can now take array, iterator, context + as the argument list. +
  • +
  • + The times function now returns the mapped array of iterator + results. +
  • +
  • + Simplified and fixed bugs in throttle. +
  • +
+

+ +

+ 1.4.2Oct. 1, 2012Diff
+

    +
  • + For backwards compatibility, returned to pre-1.4.0 behavior when + passing null to iteration functions. They now become no-ops + again. +
  • +
+

+ +

+ 1.4.1Oct. 1, 2012Diff
+

    +
  • + Fixed a 1.4.0 regression in the lastIndexOf function. +
  • +
+

+ +

+ 1.4.0Sept. 27, 2012Diff
+

    +
  • + Added a pairs function, for turning a JavaScript object + into [key, value] pairs ... as well as an object + function, for converting an array of [key, value] pairs + into an object. +
  • +
  • + Added a countBy function, for counting the number of objects + in a list that match a certain criteria. +
  • +
  • + Added an invert function, for performing a simple inversion + of the keys and values in an object. +
  • +
  • + Added a where function, for easy cases of filtering a list + for objects with specific values. +
  • +
  • + Added an omit function, for filtering an object to remove + certain keys. +
  • +
  • + Added a random function, to return a random number in a + given range. +
  • +
  • + _.debounce'd functions now return their last updated value, + just like _.throttle'd functions do. +
  • +
  • + The sortBy function now runs a stable sort algorithm. +
  • +
  • + Added the optional fromIndex option to indexOf and + lastIndexOf. +
  • +
  • + "Sparse" arrays are no longer supported in Underscore iteration + functions. Use a for loop instead (or better yet, an object). +
  • +
  • + The min and max functions may now be called on + very large arrays. +
  • +
  • + Interpolation in templates now represents null and + undefined as the empty string. +
  • +
  • + Underscore iteration functions no longer accept null values + as a no-op argument. You'll get an early error instead. +
  • +
  • + A number of edge-cases fixes and tweaks, which you can spot in the + diff. + Depending on how you're using Underscore, 1.4.0 may be more + backwards-incompatible than usual — please test when you upgrade. +
  • +
+

+ +

+ 1.3.3April 10, 2012
+

    +
  • + Many improvements to _.template, which now provides the + source of the template function as a property, for potentially + even more efficient pre-compilation on the server-side. You may now + also set the variable option when creating a template, + which will cause your passed-in data to be made available under the + variable you named, instead of using a with statement — + significantly improving the speed of rendering the template. +
  • +
  • + Added the pick function, which allows you to filter an + object literal with a whitelist of allowed property names. +
  • +
  • + Added the result function, for convenience when working + with APIs that allow either functions or raw properties. +
  • +
  • + Added the isFinite function, because sometimes knowing that + a value is a number just ain't quite enough. +
  • +
  • + The sortBy function may now also be passed the string name + of a property to use as the sort order on each object. +
  • +
  • + Fixed uniq to work with sparse arrays. +
  • +
  • + The difference function now performs a shallow flatten + instead of a deep one when computing array differences. +
  • +
  • + The debounce function now takes an immediate + parameter, which will cause the callback to fire on the leading + instead of the trailing edge. +
  • +
+

+ +

+ 1.3.1Jan. 23, 2012
+

    +
  • + Added an _.has function, as a safer way to use hasOwnProperty. +
  • +
  • + Added _.collect as an alias for _.map. Smalltalkers, rejoice. +
  • +
  • + Reverted an old change so that _.extend will correctly copy + over keys with undefined values again. +
  • +
  • + Bugfix to stop escaping slashes within interpolations in _.template. +
  • +
+

+ +

+ 1.3.0Jan. 11, 2012
+

    +
  • + Removed AMD (RequireJS) support from Underscore. If you'd like to use + Underscore with RequireJS, you can load it as a normal script, wrap + or patch your copy, or download a forked version. +
  • +
+

+ +

+ 1.2.4Jan. 4, 2012
+

    +
  • + You now can (and probably should, as it's simpler) + write _.chain(list) + instead of _(list).chain(). +
  • +
  • + Fix for escaped characters in Underscore templates, and for supporting + customizations of _.templateSettings that only define one or + two of the required regexes. +
  • +
  • + Fix for passing an array as the first argument to an _.wrap'd function. +
  • +
  • + Improved compatibility with ClojureScript, which adds a call + function to String.prototype. +
  • +
+

+ +

+ 1.2.3Dec. 7, 2011
+

    +
  • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
  • +
  • + Sparse array support of _.indexOf, _.lastIndexOf. +
  • +
  • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
  • +
+

+ +

+ 1.2.2Nov. 14, 2011
+

    +
  • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
  • +
  • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
  • +
  • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
  • +
  • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
  • +
+

+ +

+ 1.2.1Oct. 24, 2011
+

    +
  • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
  • +
  • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
  • +
  • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
  • +
  • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
  • +
  • + Most of the _.is[Type] checks no longer ducktype. +
  • +
  • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
  • +
  • + _.clone no longer wraps non-object types in Objects. +
  • +
  • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
  • +
+

+ +

+ 1.2.0Oct. 5, 2011
+

    +
  • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
  • +
  • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
  • +
  • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
  • +
  • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
  • +
  • + _.last now takes an optional argument which will return the last + N elements of the list. +
  • +
  • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
  • +
+

+ +

+ 1.1.7July 13, 2011
+ Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

+ +

+ 1.1.6April 18, 2011
+ Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

+ +

+ 1.1.5Mar 20, 2011
+ Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

+ +

+ 1.1.4Jan 9, 2011
+ Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

+ +

+ 1.1.3Dec 1, 2010
+ In CommonJS, Underscore may now be required with just:
+ var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

+ +

+ 1.1.2
+ Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

+ +

+ 1.1.1
+ Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

+ +

+ 1.1.0
+ The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

+ +

+ 1.0.4
+ Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

+ +

+ 1.0.3
+ Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

+ +

+ 1.0.2
+ Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

+ +

+ 1.0.1
+ Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

+ +

+ 1.0.0
+ Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

+ +

+ 0.6.0
+ Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

+ +

+ 0.5.8
+ Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

+ +

+ 0.5.7
+ A safer implementation of _.isArguments, and a + faster _.isNumber,
thanks to + Jed Schmidt. +

+ +

+ 0.5.6
+ Customizable delimiters for _.template, contributed by + Noah Sloan. +

+ +

+ 0.5.5
+ Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

+ +

+ 0.5.4
+ Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

+ +

+ 0.5.2
+ New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

+ +

+ 0.5.1
+ Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

+ +

+ 0.5.0
+ [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

+ +

+ 0.4.7
+ Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

+ +

+ 0.4.6
+ Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

+ +

+ 0.4.5
+ Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

+ +

+ 0.4.4
+ Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

+ +

+ 0.4.3
+ Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

+ +

+ 0.4.2
+ Renamed the unwrapping function to value, for clarity. +

+ +

+ 0.4.1
+ Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

+ +

+ 0.4.0
+ All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

+ +

+ 0.3.3
+ Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

+ +

+ 0.3.2
+ Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

+ +

+ 0.3.1
+ All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

+ +

+ 0.3.0
+ Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

+ +

+ 0.2.0
+ Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

+ +

+ 0.1.1
+ Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

+ +

+ 0.1.0
+ Initial release of Underscore.js. +

+ +

+ + A DocumentCloud Project + +

+ +
+ +
+ + + + + + diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.js new file mode 100644 index 000000000..2cf0ca5b0 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/package.json new file mode 100644 index 000000000..636df0641 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/package.json @@ -0,0 +1,39 @@ +{ + "name": "underscore", + "description": "JavaScript's functional programming helper library.", + "homepage": "http://underscorejs.org", + "keywords": [ + "util", + "functional", + "server", + "client", + "browser" + ], + "author": { + "name": "Jeremy Ashkenas", + "email": "jeremy@documentcloud.org" + }, + "repository": { + "type": "git", + "url": "git://github.com/documentcloud/underscore.git" + }, + "main": "underscore.js", + "version": "1.4.4", + "devDependencies": { + "phantomjs": "0.2.2" + }, + "scripts": { + "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true" + }, + "readme": " __\n /\\ \\ __\n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____\n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\\n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n \\ \\____/\n \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/documentcloud/underscore/issues" + }, + "_id": "underscore@1.4.4", + "dist": { + "shasum": "11bea3dc0ae12a258fbcac937e7267ab1e326400" + }, + "_from": "underscore@1.4.x", + "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore-min.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore-min.js new file mode 100644 index 000000000..c1d9d3aed --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore-min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore.js new file mode 100644 index 000000000..a12f0d96c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/underscore/underscore.js @@ -0,0 +1,1226 @@ +// Underscore.js 1.4.4 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.4.4'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? null : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value || _.identity); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(concat.apply(ArrayProto, arguments)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + var args = slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(slice.call(arguments))); + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/package.json b/node_modules/grunt-contrib-jshint/node_modules/jshint/package.json new file mode 100644 index 000000000..329ef660e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/package.json @@ -0,0 +1,74 @@ +{ + "name": "jshint", + "version": "2.1.11", + "homepage": "http://jshint.com/", + "description": "Static analysis tool for JavaScript", + "author": { + "name": "Anton Kovalyov", + "email": "anton@kovalyov.net", + "url": "http://anton.kovalyov.net/" + }, + "repository": { + "type": "git", + "url": "https://github.com/jshint/jshint.git" + }, + "bugs": { + "url": "https://github.com/jshint/jshint/issues" + }, + "bin": { + "jshint": "./bin/jshint" + }, + "scripts": { + "build": "node bin/build", + "test": "nodeunit tests tests/regression tests/unit", + "pretest": "jshint src" + }, + "main": "./src/jshint.js", + "dependencies": { + "shelljs": "0.1.x", + "underscore": "1.4.x", + "cli": "0.4.x", + "minimatch": "0.x.x", + "console-browserify": "0.1.x" + }, + "devDependencies": { + "jshint": "2.1.x", + "shelljs": "0.1.x", + "browserify": "2.12.x", + "coveraje": "0.2.x", + "nodeunit": "0.8.x", + "sinon": "1.7.x" + }, + "jshintConfig": { + "boss": true, + "node": true, + "strict": true, + "white": true, + "smarttabs": true, + "maxlen": 100, + "newcap": false, + "undef": true, + "unused": true, + "onecase": true, + "indent": 2 + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/jshint/jshint/blob/master/LICENSE" + } + ], + "preferGlobal": true, + "files": [ + "bin", + "src" + ], + "readme": "JSHint, A Static Code Analysis Tool for JavaScript\n--------------------------------------------------\n\n\\[ [Use it online](http://jshint.com/) • [About](http://jshint.com/about/) • \n[Docs](http://jshint.com/docs/) • [FAQ](http://jshint.com/docs/faq) • \n[Install](http://jshint.com/install/) • [Hack](http://jshint.com/hack/) • \n[Blog](http://jshint.com/blog/) • [Twitter](https://twitter.com/jshint/) \\]\n\n[![Build Status](https://travis-ci.org/jshint/jshint.png?branch=master)](https://travis-ci.org/jshint/jshint)\n[![NPM version](https://badge.fury.io/js/jshint.png)](http://badge.fury.io/js/jshint)\n\nJSHint is a community-driven tool to detect errors and potential problems\nin JavaScript code and to enforce your team’s coding conventions. It is\nvery flexible so you can easily adjust it to your particular coding guidelines\nand the environment you expect your code to execute in.\n\n#### Reporting a bug\n\nTo report a bug simply create a\n[new GitHub Issue](https://github.com/jshint/jshint/issues/new) and describe\nyour problem or suggestion. We welcome all kind of feedback regarding\nJSHint including but not limited to:\n\n * When JSHint doesn't work as expected\n * When JSHint complains about valid JavaScript code that works in all browsers\n * When you simply want a new option or feature\n\nBefore reporting a bug look around to see if there are any open or closed tickets\nthat cover your issue. And remember the wisdom: pull request > bug report > tweet.\n\n\n#### License\n\nJSHint is distributed under the MIT License. One file and one file only\n(src/stable/jshint.js) is distributed under the slightly modified MIT License.\n\n\n#### Thank you!\n\nWe really appreciate all kind of feedback and contributions. Thanks for using and supporting JSHint!\n", + "readmeFilename": "README.md", + "_id": "jshint@2.1.11", + "dist": { + "shasum": "f5894f673d4fc0c89836d53c2068e7b3c89fbe62" + }, + "_from": "jshint@~2.1.10", + "_resolved": "https://registry.npmjs.org/jshint/-/jshint-2.1.11.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/cli.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/cli.js new file mode 100644 index 000000000..d4fcd476d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/cli.js @@ -0,0 +1,506 @@ +"use strict"; + +var cli = require("cli"); +var path = require("path"); +var shjs = require("shelljs"); +var minimatch = require("minimatch"); +var JSHINT = require("./jshint.js").JSHINT; +var defReporter = require("./reporters/default").reporter; + +var OPTIONS = { + "config": ["c", "Custom configuration file", "string", false ], + "reporter": ["reporter", "Custom reporter (|jslint|checkstyle)", "string", undefined ], + "exclude": ["exclude", + "Exclude files matching the given filename pattern (same as .jshintignore)", "string", null], + "verbose": ["verbose", "Show message codes"], + "show-non-errors": ["show-non-errors", "Show additional data generated by jshint"], + "extra-ext": ["e", + "Comma-separated list of file extensions to use (default is .js)", "string", ""], + + // Deprecated options. + "jslint-reporter": [ + "jslint-reporter", + deprecated("Use a jslint compatible reporter", "--reporter=jslint") + ], + + "checkstyle-reporter": [ + "checkstyle-reporter", + deprecated("Use a CheckStyle compatible XML reporter", "--reporter=checkstyle") + ] +}; + +/** + * Returns the same text but with a deprecation notice. + * Useful for options descriptions. + * + * @param {string} text + * @param {string} alt (optional) Alternative command to include in the + * deprecation notice. + * + * @returns {string} + */ +function deprecated(text, alt) { + if (!alt) { + return text + " (DEPRECATED)"; + } + + return text + " (DEPRECATED, use " + alt + " instead)"; +} + +/** + * Removes JavaScript comments from a string by replacing + * everything between block comments and everything after + * single-line comments in a non-greedy way. + * + * English version of the regex: + * match '/*' + * then match zero or more instances of any character (incl. \n) + * except for instances of '* /' (without a space, obv.) + * then match '* /' (again, without a space) + * + * @param {string} str a string with potential JavaScript comments. + * @returns {string} a string without JavaScript comments. + */ +function removeComments(str) { + str = str || ""; + + str = str.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, ""); + str = str.replace(/\/\/[^\n\r]*/g, ""); // Everything after '//' + + return str; +} + +/** + * Tries to find a configuration file in either project directory + * or in the home directory. Configuration files are named + * '.jshintrc'. + * + * @param {string} file path to the file to be linted + * @returns {string} a path to the config file + */ +function findConfig(file) { + var dir = path.dirname(path.resolve(file)); + var envs = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; + var home = path.normalize(path.join(envs, ".jshintrc")); + + var proj = findFile(".jshintrc", dir); + if (proj) + return proj; + + if (shjs.test("-e", home)) + return home; + + return null; +} + +/** + * Tries to find JSHint configuration within a package.json file + * (if any). It search in the current directory and then goes up + * all the way to the root just like findFile. + * + * @param {string} file path to the file to be linted + * @returns {object} config object + */ +function loadNpmConfig(file) { + var dir = path.dirname(path.resolve(file)); + var fp = findFile("package.json", dir); + + if (!fp) + return null; + + return require(fp).jshintConfig || null; +} + +/** + * Tries to import a reporter file and returns its reference. + * + * @param {string} fp a path to the reporter file + * @returns {object} imported module for the reporter or 'null' + * if a module cannot be imported. + */ +function loadReporter(fp) { + try { + return require(fp).reporter; + } catch (err) { + return null; + } +} + +// Storage for memoized results from find file +// Should prevent lots of directory traversal & +// lookups when liniting an entire project +var findFileResults = {}; + +/** + * Searches for a file with a specified name starting with + * 'dir' and going all the way up either until it finds the file + * or hits the root. + * + * @param {string} name filename to search for (e.g. .jshintrc) + * @param {string} dir directory to start search from (default: + * current working directory) + * + * @returns {string} normalized filename + */ +function findFile(name, dir) { + dir = dir || process.cwd(); + + var filename = path.normalize(path.join(dir, name)); + if (findFileResults[filename] !== undefined) { + return findFileResults[filename]; + } + + var parent = path.resolve(dir, "../"); + + if (shjs.test("-e", filename)) { + findFileResults[filename] = filename; + return filename; + } + + if (dir === parent) { + findFileResults[filename] = null; + return null; + } + + return findFile(name, parent); +} + +/** + * Loads a list of files that have to be skipped. JSHint assumes that + * the list is located in a file called '.jshintignore'. + * + * @return {array} a list of files to ignore. + */ +function loadIgnores(exclude) { + var file = findFile(".jshintignore"); + + if (!file && !exclude) { + return []; + } + + var lines = (file ? shjs.cat(file) : "").split("\n"); + lines.unshift(exclude || ""); + + return lines + .filter(function (line) { + return !!line.trim(); + }) + .map(function (line) { + if (line[0] === "!") + return "!" + path.resolve(path.dirname(file), line.substr(1).trim()); + + return path.resolve(path.dirname(file), line.trim()); + }); +} + +/** + * Checks whether we should ignore a file or not. + * + * @param {string} fp a path to a file + * @param {array} patterns a list of patterns for files to ignore + * + * @return {boolean} 'true' if file should be ignored, 'false' otherwise. + */ +function isIgnored(fp, patterns) { + return patterns.some(function (ip) { + if (minimatch(path.resolve(fp), ip, { nocase: true })) { + return true; + } + + if (path.resolve(fp) === ip) { + return true; + } + + if (shjs.test("-d", fp) && ip.match(/^[^\/]*\/?$/) && + fp.match(new RegExp("^" + ip + ".*"))) { + return true; + } + }); +} + +/** + * Recursively gather all files that need to be linted, + * excluding those that user asked to ignore. + * + * @param {string} fp a path to a file or directory to lint + * @param {array} files a pointer to an array that stores a list of files + * @param {array} ignores a list of patterns for files to ignore + * @param {array} ext a list of non-dot-js extensions to lint + */ +function collect(fp, files, ignores, ext) { + if (ignores && isIgnored(fp, ignores)) { + return; + } + + if (!shjs.test("-e", fp)) { + cli.error("Can't open " + fp); + return; + } + + if (shjs.test("-d", fp)) { + shjs.ls(fp).forEach(function (item) { + var itempath = path.join(fp, item); + if (shjs.test("-d", itempath) || item.match(ext)) { + collect(itempath, files, ignores, ext); + } + }); + + return; + } + + files.push(fp); +} + +/** + * Runs JSHint against provided file and saves the result + * + * @param {string} code code that needs to be linted + * @param {object} results a pointer to an object with results + * @param {object} config an object with JSHint configuration + * @param {object} data a pointer to an object with extra data + * @param {string} file (optional) file name that is being linted + */ +function lint(code, results, config, data, file) { + var globals; + var lintData; + var buffer = []; + + config = config || {}; + config = JSON.parse(JSON.stringify(config)); + + if (config.prereq) { + config.prereq.forEach(function (fp) { + fp = path.join(config.dirname, fp); + if (shjs.test("-e", fp)) + buffer.push(shjs.cat(fp)); + }); + delete config.prereq; + } + + if (config.globals) { + globals = config.globals; + delete config.globals; + } + + delete config.dirname; + buffer.push(code); + buffer = buffer.join("\n"); + buffer = buffer.replace(/^\uFEFF/, ""); // Remove potential Unicode BOM. + + if (!JSHINT(buffer, config, globals)) { + JSHINT.errors.forEach(function (err) { + if (err) { + results.push({ file: file || "stdin", error: err }); + } + }); + } + + lintData = JSHINT.data(); + + if (lintData) { + lintData.file = file || "stdin"; + data.push(lintData); + } +} + +var exports = { + /** + * Loads and parses a configuration file. + * + * @param {string} fp a path to the config file + * @returns {object} config object + */ + loadConfig: function (fp) { + if (!fp) { + return {}; + } + + if (!shjs.test("-e", fp)) { + cli.error("Can't find config file: " + fp); + process.exit(1); + } + + try { + var config = JSON.parse(removeComments(shjs.cat(fp))); + config.dirname = path.dirname(fp); + return config; + } catch (err) { + cli.error("Can't parse config file: " + fp); + process.exit(1); + } + }, + + /** + * Gathers all files that need to be linted + * + * @param {object} post-processed options from 'interpret': + * args - CLI arguments + * ignores - A list of files/dirs to ignore (defaults to .jshintignores) + * extensions - A list of non-dot-js extensions to check + */ + gather: function (opts) { + var files = []; + + var reg = new RegExp("\\.(js" + + (!opts.extensions ? "" : "|" + + opts.extensions.replace(/,/g, "|").replace(/[\. ]/g, "")) + ")$"); + + var ignores = !opts.ignores ? loadIgnores() : opts.ignores.map(function (target) { + return path.resolve(target); + }); + + opts.args.forEach(function (target) { + collect(target, files, ignores, reg); + }); + + return files; + }, + + /** + * Gathers all files that need to be linted, lints them, sends them to + * a reporter and returns the overall result. + * + * @param {object} post-processed options from 'interpret': + * args - CLI arguments + * config - Configuration object + * reporter - Reporter function + * ignores - A list of files/dirs to ignore + * extensions - A list of non-dot-js extensions to check + * @param {function} cb a callback to call when function is finished + * asynchronously. + * + * @returns {bool} 'true' if all files passed, 'false' otherwise and 'null' + * when function will be finished asynchronously. + */ + run: function (opts, cb) { + var files = exports.gather(opts); + var results = []; + var data = []; + + if (opts.useStdin) { + cli.withStdin(function (code) { + lint(code, results, opts.config || {}, data); + (opts.reporter || defReporter)(results, data, { verbose: opts.verbose }); + cb(results.length === 0); + }); + + return null; + } + + files.forEach(function (file) { + var config = opts.config || loadNpmConfig(file) || exports.loadConfig(findConfig(file)); + var code; + + try { + code = shjs.cat(file); + } catch (err) { + cli.error("Can't open " + file); + process.exit(1); + } + + lint(code, results, config, data, file); + }); + + (opts.reporter || defReporter)(results, data, { verbose: opts.verbose }); + return results.length === 0; + }, + + /** + * Helper exposed for testing. + * Used to determine is stdout has any buffered output before exiting the program + */ + getBufferSize: function () { + return process.stdout.bufferSize; + }, + + /** + * Main entrance function. Parses arguments and calls 'run' when + * its done. This function is called from bin/jshint file. + * + * @param {object} args, arguments in the process.argv format. + */ + interpret: function (args) { + cli.setArgv(args); + cli.options = {}; + + cli.enable("version", "glob", "help"); + cli.setApp(path.resolve(__dirname + "/../package.json")); + + var options = cli.parse(OPTIONS); + // Use config file if specified + var config; + if (options.config) { + config = exports.loadConfig(options.config); + } + + switch (true) { + // JSLint reporter + case options.reporter === "jslint": + case options["jslint-reporter"]: + options.reporter = "./reporters/jslint_xml.js"; + break; + + // CheckStyle (XML) reporter + case options.reporter === "checkstyle": + case options["checkstyle-reporter"]: + options.reporter = "./reporters/checkstyle.js"; + break; + + // Reporter that displays additional JSHint data + case options["show-non-errors"]: + options.reporter = "./reporters/non_error.js"; + break; + + // Custom reporter + case options.reporter !== undefined: + options.reporter = path.resolve(process.cwd(), options.reporter); + } + + var reporter; + if (options.reporter) { + reporter = loadReporter(options.reporter); + + if (reporter === null) { + cli.error("Can't load reporter file: " + options.reporter); + process.exit(1); + } + } + + // This is a hack. exports.run is both sync and async function + // because I needed stdin support (and cli.withStdin is async) + // and was too lazy to change tests. + + function done(passed) { + /*jshint eqnull:true */ + + if (passed == null) + return; + + // Patch as per https://github.com/visionmedia/mocha/issues/333 + // fixes issues with piped output on Windows. + // Root issue is here https://github.com/joyent/node/issues/3584 + function exit() { process.exit(passed ? 0 : 2); } + try { + if (exports.getBufferSize()) { + process.stdout.once('drain', exit); + } else { + exit(); + } + } catch (err) { + exit(); + } + } + + done(exports.run({ + args: cli.args, + config: config, + reporter: reporter, + ignores: loadIgnores(options.exclude), + extensions: options["extra-ext"], + verbose: options.verbose, + useStdin: {"-": true, "/dev/stdin": true}[args[args.length - 1]] + }, done)); + } +}; + +module.exports = exports; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/jshint.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/jshint.js new file mode 100644 index 000000000..37ff87c32 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/jshint.js @@ -0,0 +1,4872 @@ +/*! + * JSHint, by JSHint Community. + * + * This file (and this file only) is licensed under the same slightly modified + * MIT license that JSLint is. It stops evil-doers everywhere: + * + * Copyright (c) 2002 Douglas Crockford (www.JSLint.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * The Software shall be used for Good, not Evil. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/*jshint quotmark:double */ +/*global console:true */ +/*exported console */ + +var _ = require("underscore"); +var events = require("events"); +var vars = require("./vars.js"); +var messages = require("./messages.js"); +var Lexer = require("./lex.js").Lexer; +var reg = require("./reg.js"); +var state = require("./state.js").state; +var style = require("./style.js"); + +// We need this module here because environments such as IE and Rhino +// don't necessarilly expose the 'console' API and browserify uses +// it to log things. It's a sad state of affair, really. +var console = require("console-browserify"); + +// We build the application inside a function so that we produce only a singleton +// variable. That function will be invoked immediately, and its return value is +// the JSHINT function itself. + +var JSHINT = (function () { + "use strict"; + + var anonname, // The guessed name for anonymous functions. + api, // Extension API + + // These are operators that should not be used with the ! operator. + bang = { + "<" : true, + "<=" : true, + "==" : true, + "===": true, + "!==": true, + "!=" : true, + ">" : true, + ">=" : true, + "+" : true, + "-" : true, + "*" : true, + "/" : true, + "%" : true + }, + + // These are the JSHint boolean options. + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + bitwise : true, // if bitwise operators should not be allowed + boss : true, // if advanced usage of assignments should be allowed + browser : true, // if the standard browser globals should be predefined + camelcase : true, // if identifiers should be required in camel case + couch : true, // if CouchDB globals should be predefined + curly : true, // if curly braces around all blocks should be required + debug : true, // if debugger statements should be allowed + devel : true, // if logging globals should be predefined (console, alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es3 : true, // if ES3 syntax should be allowed + es5 : true, // if ES5 syntax should be allowed (is now set per default) + esnext : true, // if es.next specific syntax should be allowed + moz : true, // if mozilla specific syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + funcscope : true, // if only function scope should be used for scope tests + gcl : true, // if JSHint should be compatible with Google Closure Linter + globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be allowed + jquery : true, // if jQuery globals should be predefined + lastsemic : true, // if semicolons may be ommitted for the trailing + // statements inside of a one-line blocks. + laxbreak : true, // if line breaks should not be checked + laxcomma : true, // if line breaks should not be checked around commas + loopfunc : true, // if functions should be allowed to be defined within + // loops + mootools : true, // if MooTools globals should be predefined + multistr : true, // allow multiline strings + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be + // disallowed + node : true, // if the Node.js environment globals should be + // predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nonstandard : true, // if non-standard (but widely adopted) globals should + // be predefined + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be + // allowed + passfail : true, // if the scan should stop on first error + phantom : true, // if PhantomJS symbols should be allowed + plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be + // predefined + rhino : true, // if the Rhino environment globals should be predefined + shelljs : true, // if ShellJS globals should be predefined + typed : true, // if typed array globals should be predefined + undef : true, // if variables should be declared before used + scripturl : true, // if script-targeted URLs should be tolerated + shadow : true, // if variable shadowing should be tolerated + smarttabs : true, // if smarttabs should be tolerated + // (http://www.emacswiki.org/emacs/SmartTabs) + strict : true, // require the "use strict"; pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` + // should be tolerated + trailing : true, // if trailing whitespace rules apply + validthis : true, // if 'this' inside a non-constructor function is valid. + // This is a function scoped option only. + withstmt : true, // if with statements should be allowed + white : true, // if strict whitespace rules apply + worker : true, // if Web Worker script symbols should be allowed + wsh : true, // if the Windows Scripting Host environment globals + // should be predefined + yui : true, // YUI variables should be predefined + + // Obsolete options + onecase : true, // if one case switch statements should be allowed + regexp : true, // if the . should not be allowed in regexp literals + regexdash : true // if unescaped first/last dash (-) inside brackets + // should be tolerated + }, + + // These are the JSHint options that can take any value + // (we use this object to detect invalid options) + valOptions = { + maxlen : false, + indent : false, + maxerr : false, + predef : false, + quotmark : false, //'single'|'double'|true + scope : false, + maxstatements: false, // {int} max statements per function + maxdepth : false, // {int} max nested block depth per function + maxparams : false, // {int} max params per function + maxcomplexity: false, // {int} max cyclomatic complexity per function + unused : true, // warn if variables are unused. Available options: + // false - don't check for unused variables + // true - "vars" + check last function param + // "vars" - skip checking unused function params + // "strict" - "vars" + check all function params + latedef : false // warn if the variable is used before its definition + // false - don't emit any warnings + // true - warn if any variable is used before its definition + // "nofunc" - warn for any variable but function declarations + }, + + // These are JSHint boolean options which are shared with JSLint + // where the definition in JSHint is opposite JSLint + invertedOptions = { + bitwise : true, + forin : true, + newcap : true, + nomen : true, + plusplus: true, + regexp : true, + undef : true, + white : true, + + // Inverted and renamed, use JSHint name here + eqeqeq : true, + onevar : true, + strict : true + }, + + // These are JSHint boolean options which are shared with JSLint + // where the name has been changed but the effect is unchanged + renamedOptions = { + eqeq : "eqeqeq", + vars : "onevar", + windows: "wsh", + sloppy : "strict" + }, + + declared, // Globals that were declared using /*global ... */ syntax. + exported, // Variables that are used outside of the current file. + + functionicity = [ + "closure", "exception", "global", "label", + "outer", "unused", "var" + ], + + funct, // The current function + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + lookahead, + lex, + member, + membersOnly, + noreach, + predefined, // Global variables defined by option + + scope, // The current scope + stack, + unuseds, + urls, + warnings, + + extraModules = [], + emitter = new events.EventEmitter(); + + function checkOption(name, t) { + name = name.trim(); + + if (/^[+-]W\d{3}$/g.test(name)) { + return true; + } + + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + if (t.type !== "jslint") { + error("E001", t, name); + return false; + } + } + + return true; + } + + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; + } + + function isIdentifier(tkn, value) { + if (!tkn) + return false; + + if (!tkn.identifier || tkn.value !== value) + return false; + + return true; + } + + function isReserved(token) { + if (!token.reserved) { + return false; + } + var meta = token.meta; + + if (meta && meta.isFutureReservedWord && state.option.inES5()) { + // ES3 FutureReservedWord in an ES5 environment. + if (!meta.es5) { + return false; + } + + // Some ES5 FutureReservedWord identifiers are active only + // within a strict mode environment. + if (meta.strictOnly) { + if (!state.option.strict && !state.directive["use strict"]) { + return false; + } + } + + if (token.isProperty) { + return false; + } + } + + return true; + } + + function supplant(str, data) { + return str.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = data[b]; + return typeof r === "string" || typeof r === "number" ? r : a; + }); + } + + function combine(t, o) { + var n; + for (n in o) { + if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) { + t[n] = o[n]; + } + } + } + + function updatePredefined() { + Object.keys(JSHINT.blacklist).forEach(function (key) { + delete predefined[key]; + }); + } + + function assume() { + if (state.option.es5) { + warning("I003"); + } + if (state.option.couch) { + combine(predefined, vars.couch); + } + + if (state.option.rhino) { + combine(predefined, vars.rhino); + } + + if (state.option.shelljs) { + combine(predefined, vars.shelljs); + combine(predefined, vars.node); + } + if (state.option.typed) { + combine(predefined, vars.typed); + } + + if (state.option.phantom) { + combine(predefined, vars.phantom); + } + + if (state.option.prototypejs) { + combine(predefined, vars.prototypejs); + } + + if (state.option.node) { + combine(predefined, vars.node); + combine(predefined, vars.typed); + } + + if (state.option.devel) { + combine(predefined, vars.devel); + } + + if (state.option.dojo) { + combine(predefined, vars.dojo); + } + + if (state.option.browser) { + combine(predefined, vars.browser); + combine(predefined, vars.typed); + } + + if (state.option.nonstandard) { + combine(predefined, vars.nonstandard); + } + + if (state.option.jquery) { + combine(predefined, vars.jquery); + } + + if (state.option.mootools) { + combine(predefined, vars.mootools); + } + + if (state.option.worker) { + combine(predefined, vars.worker); + } + + if (state.option.wsh) { + combine(predefined, vars.wsh); + } + + if (state.option.globalstrict && state.option.strict !== false) { + state.option.strict = true; + } + + if (state.option.yui) { + combine(predefined, vars.yui); + } + + // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz + + state.option.inMoz = function (strict) { + if (strict) { + return state.option.moz && !state.option.esnext; + } + return state.option.moz; + }; + + state.option.inESNext = function (strict) { + if (strict) { + return !state.option.moz && state.option.esnext; + } + return state.option.moz || state.option.esnext; + }; + + state.option.inES5 = function (/* strict */) { + return !state.option.es3; + }; + + state.option.inES3 = function (strict) { + if (strict) { + return !state.option.moz && !state.option.esnext && state.option.es3; + } + return state.option.es3; + }; + } + + // Produce an error warning. + function quit(code, line, chr) { + var percentage = Math.floor((line / state.lines.length) * 100); + var message = messages.errors[code].desc; + + throw { + name: "JSHintError", + line: line, + character: chr, + message: message + " (" + percentage + "% scanned).", + raw: message, + code: code + }; + } + + function isundef(scope, code, token, a) { + return JSHINT.undefs.push([scope, code, token, a]); + } + + function warning(code, t, a, b, c, d) { + var ch, l, w, msg; + + if (/^W\d{3}$/.test(code)) { + if (state.ignored[code]) + return; + + msg = messages.warnings[code]; + } else if (/E\d{3}/.test(code)) { + msg = messages.errors[code]; + } else if (/I\d{3}/.test(code)) { + msg = messages.info[code]; + } + + t = t || state.tokens.next; + if (t.id === "(end)") { // `~ + t = state.tokens.curr; + } + + l = t.line || 0; + ch = t.from || 0; + + w = { + id: "(error)", + raw: msg.desc, + code: msg.code, + evidence: state.lines[l - 1] || "", + line: l, + character: ch, + scope: JSHINT.scope, + a: a, + b: b, + c: c, + d: d + }; + + w.reason = supplant(msg.desc, w); + JSHINT.errors.push(w); + + if (state.option.passfail) { + quit("E042", l, ch); + } + + warnings += 1; + if (warnings >= state.option.maxerr) { + quit("E043", l, ch); + } + + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + + // Tracking of "internal" scripts, like eval containing a static string + function addInternalSrc(elem, src) { + var i; + i = { + id: "(internal)", + elem: elem, + value: src + }; + JSHINT.internals.push(i); + return i; + } + + function addlabel(t, type, tkn, islet) { + // Define t in the current function in the current scope. + if (type === "exception") { + if (_.has(funct["(context)"], t)) { + if (funct[t] !== true && !state.option.node) { + warning("W002", state.tokens.next, t); + } + } + } + + if (_.has(funct, t) && !funct["(global)"]) { + if (funct[t] === true) { + if (state.option.latedef) { + if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) || + !_.contains([funct[t], type], "unction")) { + warning("W003", state.tokens.next, t); + } + } + } else { + if (!state.option.shadow && type !== "exception" || + (funct["(blockscope)"].getlabel(t))) { + warning("W004", state.tokens.next, t); + } + } + } + + // a double definition of a let variable in same block throws a TypeError + if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) { + error("E044", state.tokens.next, t); + } + + // if the identifier is from a let, adds it only to the current blockscope + if (islet) { + funct["(blockscope)"].current.add(t, type, state.tokens.curr); + } else { + + funct[t] = type; + + if (tkn) { + funct["(tokens)"][t] = tkn; + } + + if (funct["(global)"]) { + global[t] = funct; + if (_.has(implied, t)) { + if (state.option.latedef) { + if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) || + !_.contains([funct[t], type], "unction")) { + warning("W003", state.tokens.next, t); + } + } + + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + } + + function doOption() { + var nt = state.tokens.next; + var body = nt.body.split(",").map(function (s) { return s.trim(); }); + var predef = {}; + + if (nt.type === "globals") { + body.forEach(function (g) { + g = g.split(":"); + var key = (g[0] || "").trim(); + var val = (g[1] || "").trim(); + + if (key.charAt(0) === "-") { + key = key.slice(1); + val = false; + + JSHINT.blacklist[key] = key; + updatePredefined(); + } else { + predef[key] = (val === "true"); + } + }); + + combine(predefined, predef); + + for (var key in predef) { + if (_.has(predef, key)) { + declared[key] = nt; + } + } + } + + if (nt.type === "exported") { + body.forEach(function (e) { + exported[e] = true; + }); + } + + if (nt.type === "members") { + membersOnly = membersOnly || {}; + + body.forEach(function (m) { + var ch1 = m.charAt(0); + var ch2 = m.charAt(m.length - 1); + + if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) { + m = m + .substr(1, m.length - 2) + .replace("\\b", "\b") + .replace("\\t", "\t") + .replace("\\n", "\n") + .replace("\\v", "\v") + .replace("\\f", "\f") + .replace("\\r", "\r") + .replace("\\\\", "\\") + .replace("\\\"", "\""); + } + + membersOnly[m] = false; + }); + } + + var numvals = [ + "maxstatements", + "maxparams", + "maxdepth", + "maxcomplexity", + "maxerr", + "maxlen", + "indent" + ]; + + if (nt.type === "jshint" || nt.type === "jslint") { + body.forEach(function (g) { + g = g.split(":"); + var key = (g[0] || "").trim(); + var val = (g[1] || "").trim(); + + if (!checkOption(key, nt)) { + return; + } + + if (numvals.indexOf(key) >= 0) { + + // GH988 - numeric options can be disabled by setting them to `false` + if (val !== "false") { + val = +val; + + if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) { + error("E032", nt, g[1].trim()); + return; + } + + if (key === "indent") { + state.option["(explicitIndent)"] = true; + } + state.option[key] = val; + } else { + if (key === "indent") { + state.option["(explicitIndent)"] = false; + } else { + state.option[key] = false; + } + } + + return; + } + + if (key === "validthis") { + // `validthis` is valid only within a function scope. + if (funct["(global)"]) { + error("E009"); + } else { + if (val === "true" || val === "false") { + state.option.validthis = (val === "true"); + } else { + error("E002", nt); + } + } + return; + } + + if (key === "quotmark") { + switch (val) { + case "true": + case "false": + state.option.quotmark = (val === "true"); + break; + case "double": + case "single": + state.option.quotmark = val; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "unused") { + switch (val) { + case "true": + state.option.unused = true; + break; + case "false": + state.option.unused = false; + break; + case "vars": + case "strict": + state.option.unused = val; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "latedef") { + switch (val) { + case "true": + state.option.latedef = true; + break; + case "false": + state.option.latedef = false; + break; + case "nofunc": + state.option.latedef = "nofunc"; + break; + default: + error("E002", nt); + } + return; + } + + var match = /^([+-])(W\d{3})$/g.exec(key); + if (match) { + // ignore for -W..., unignore for +W... + state.ignored[match[2]] = (match[1] === "-"); + return; + } + + var tn; + if (val === "true" || val === "false") { + if (nt.type === "jslint") { + tn = renamedOptions[key] || key; + state.option[tn] = (val === "true"); + + if (invertedOptions[tn] !== undefined) { + state.option[tn] = !state.option[tn]; + } + } else { + state.option[key] = (val === "true"); + } + + if (key === "newcap") { + state.option["(explicitNewcap)"] = true; + } + return; + } + + error("E002", nt); + }); + + assume(); + } + } + + // We need a peek function. If it has an argument, it peeks that much farther + // ahead. It is used to distinguish + // for ( var i in ... + // from + // for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + // Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (state.tokens.curr.id) { + case "(number)": + if (state.tokens.next.id === ".") { + warning("W005", state.tokens.curr); + } + break; + case "-": + if (state.tokens.next.id === "-" || state.tokens.next.id === "--") { + warning("W006"); + } + break; + case "+": + if (state.tokens.next.id === "+" || state.tokens.next.id === "++") { + warning("W007"); + } + break; + } + + if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) { + anonname = state.tokens.curr.value; + } + + if (id && state.tokens.next.id !== id) { + if (t) { + if (state.tokens.next.id === "(end)") { + error("E019", t, t.id); + } else { + error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value); + } + } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) { + warning("W116", state.tokens.next, id, state.tokens.next.value); + } + } + + state.tokens.prev = state.tokens.curr; + state.tokens.curr = state.tokens.next; + for (;;) { + state.tokens.next = lookahead.shift() || lex.token(); + + if (!state.tokens.next) { // No more tokens left, give up + quit("E041", state.tokens.curr.line); + } + + if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") { + return; + } + + if (state.tokens.next.check) { + state.tokens.next.check(); + } + + if (state.tokens.next.isSpecial) { + doOption(); + } else { + if (state.tokens.next.id !== "(endline)") { + break; + } + } + } + } + + function isInfix(token) { + return token.infix || (!token.identifier && !!token.led); + } + + function isEndOfExpr() { + var curr = state.tokens.curr; + var next = state.tokens.next; + if (next.id === ";" || next.id === "}" || next.id === ":") { + return true; + } + if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.option.inMoz(true))) { + return curr.line !== next.line; + } + return false; + } + + // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it + // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is + // like .nud except that it is only used on the first token of a statement. + // Having .fud makes it much easier to define statement-oriented languages like + // JavaScript. I retained Pratt's nomenclature. + + // .nud Null denotation + // .fud First null denotation + // .led Left denotation + // lbp Left binding power + // rbp Right binding power + + // They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false, isObject = false, isLetExpr = false; + + // if current expression is a let expression + if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.next, "let expressions"); + } + isLetExpr = true; + // create a new block scope we use only for the current expression + funct["(blockscope)"].stack(); + advance("let"); + advance("("); + state.syntax["let"].fud.call(state.syntax["let"].fud, false); + advance(")"); + } + + if (state.tokens.next.id === "(end)") + error("E006", state.tokens.curr); + + advance(); + + if (initial) { + anonname = "anonymous"; + funct["(verb)"] = state.tokens.curr.value; + } + + if (initial === true && state.tokens.curr.fud) { + left = state.tokens.curr.fud(); + } else { + if (state.tokens.curr.nud) { + left = state.tokens.curr.nud(); + } else { + error("E030", state.tokens.curr, state.tokens.curr.id); + } + + while (rbp < state.tokens.next.lbp && !isEndOfExpr()) { + isArray = state.tokens.curr.value === "Array"; + isObject = state.tokens.curr.value === "Object"; + + // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object() + // Line breaks in IfStatement heads exist to satisfy the checkJSHint + // "Line too long." error. + if (left && (left.value || (left.first && left.first.value))) { + // If the left.value is not "new", or the left.first.value is a "." + // then safely assume that this is not "new Array()" and possibly + // not "new Object()"... + if (left.value !== "new" || + (left.first && left.first.value && left.first.value === ".")) { + isArray = false; + // ...In the case of Object, if the left.value and state.tokens.curr.value + // are not equal, then safely assume that this not "new Object()" + if (left.value !== state.tokens.curr.value) { + isObject = false; + } + } + } + + advance(); + + if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") { + warning("W009", state.tokens.curr); + } + + if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") { + warning("W010", state.tokens.curr); + } + + if (left && state.tokens.curr.led) { + left = state.tokens.curr.led(left); + } else { + error("E033", state.tokens.curr, state.tokens.curr.id); + } + } + } + if (isLetExpr) { + funct["(blockscope)"].unstack(); + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (state.option.white) { + if (left.character !== right.from && left.line === right.line) { + left.from += (left.character - left.from); + warning("W011", left, left.value); + } + } + } + + function nobreak(left, right) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (state.option.white && (left.character !== right.from || left.line !== right.line)) { + warning("W012", right, right.value); + } + } + + function nospace(left, right) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (state.option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + if (state.option.white) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + + if (left.value === ";" && right.value === ";") { + return; + } + + if (left.line === right.line && left.character === right.from) { + left.from += (left.character - left.from); + warning("W013", left, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (!state.option.laxbreak && left.line !== right.line) { + warning("W014", right, right.value); + } else if (state.option.white) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (left.character === right.from) { + left.from += (left.character - left.from); + warning("W013", left, left.value); + } + } + } + + function indentation(bias) { + if (!state.option.white && !state.option["(explicitIndent)"]) { + return; + } + + if (state.tokens.next.id === "(end)") { + return; + } + + var i = indent + (bias || 0); + if (state.tokens.next.from !== i) { + warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from); + } + } + + function nolinebreak(t) { + t = t || state.tokens.curr; + if (t.line !== state.tokens.next.line) { + warning("E022", t, t.value); + } + } + + function nobreakcomma(left, right) { + if (left.line !== right.line) { + if (!state.option.laxcomma) { + if (comma.first) { + warning("I001"); + comma.first = false; + } + warning("W014", left, right.value); + } + } else if (!left.comment && left.character !== right.from && state.option.white) { + left.from += (left.character - left.from); + warning("W011", left, left.value); + } + } + + function comma(opts) { + opts = opts || {}; + + if (!opts.peek) { + nobreakcomma(state.tokens.curr, state.tokens.next); + advance(","); + } else { + nobreakcomma(state.tokens.prev, state.tokens.curr); + } + + // TODO: This is a temporary solution to fight against false-positives in + // arrays and objects with trailing commas (see GH-363). The best solution + // would be to extract all whitespace rules out of parser. + + if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") { + nonadjacent(state.tokens.curr, state.tokens.next); + } + + if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) { + // Keywords that cannot follow a comma operator. + switch (state.tokens.next.value) { + case "break": + case "case": + case "catch": + case "continue": + case "default": + case "do": + case "else": + case "finally": + case "for": + case "if": + case "in": + case "instanceof": + case "return": + case "switch": + case "throw": + case "try": + case "var": + case "let": + case "while": + case "with": + error("E024", state.tokens.next, state.tokens.next.value); + return false; + } + } + + if (state.tokens.next.type === "(punctuator)") { + switch (state.tokens.next.value) { + case "}": + case "]": + case ",": + if (opts.allowTrailing) { + return true; + } + + /* falls through */ + case ")": + error("E024", state.tokens.next, state.tokens.next.value); + return false; + } + } + return true; + } + + // Functional constructors for making the symbols that will be inherited by + // tokens. + + function symbol(s, p) { + var x = state.syntax[s]; + if (!x || typeof x !== "object") { + state.syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + function delim(s) { + return symbol(s, 0); + } + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { + x.identifier = x.reserved = true; + } + return x; + } + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === "function") ? f : function () { + this.right = expression(150); + this.arity = "unary"; + if (this.id === "++" || this.id === "--") { + if (state.option.plusplus) { + warning("W016", this, this.id); + } else if ((!this.right.identifier || isReserved(this.right)) && + this.right.id !== "." && this.right.id !== "[") { + warning("W017", this); + } + } + return this; + }; + return x; + } + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + function reserve(name, func) { + var x = type(name, func); + x.identifier = true; + x.reserved = true; + return x; + } + + function FutureReservedWord(name, meta) { + var x = type(name, (meta && meta.nud) || function () { + return this; + }); + + meta = meta || {}; + meta.isFutureReservedWord = true; + + x.value = name; + x.identifier = true; + x.reserved = true; + x.meta = meta; + + return x; + } + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === "function") { + v(this); + } + return this; + }); + } + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.infix = true; + x.led = function (left) { + if (!w) { + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + nonadjacent(state.tokens.curr, state.tokens.next); + } + if (s === "in" && left.id === "!") { + warning("W018", left, "!"); + } + if (typeof f === "function") { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function application(s) { + var x = symbol(s, 42); + + x.led = function (left) { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "arrow function syntax (=>)"); + } + + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + nonadjacent(state.tokens.curr, state.tokens.next); + + this.left = left; + this.right = doFunction(undefined, undefined, false, left); + return this; + }; + return x; + } + + function relation(s, f) { + var x = symbol(s, 100); + + x.led = function (left) { + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + nonadjacent(state.tokens.curr, state.tokens.next); + var right = expression(100); + + if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) { + warning("W019", this); + } else if (f) { + f.apply(this, [left, right]); + } + + if (!left || !right) { + quit("E041", state.tokens.curr.line); + } + + if (left.id === "!") { + warning("W018", left, "!"); + } + + if (right.id === "!") { + warning("W018", right, "!"); + } + + this.left = left; + this.right = right; + return this; + }; + return x; + } + + function isPoorRelation(node) { + return node && + ((node.type === "(number)" && +node.value === 0) || + (node.type === "(string)" && node.value === "") || + (node.type === "null" && !state.option.eqnull) || + node.type === "true" || + node.type === "false" || + node.type === "undefined"); + } + + function assignop(s, f, p) { + var x = infix(s, typeof f === "function" ? f : function (left, that) { + that.left = left; + + if (left) { + if (predefined[left.value] === false && + scope[left.value]["(global)"] === true) { + warning("W020", left); + } else if (left["function"]) { + warning("W021", left, left.value); + } + + if (funct[left.value] === "const") { + error("E013", left, left.value); + } + + if (left.id === ".") { + if (!left.left) { + warning("E031", that); + } else if (left.left.value === "arguments" && !state.directive["use strict"]) { + warning("E031", that); + } + + that.right = expression(10); + return that; + } else if (left.id === "[") { + if (state.tokens.curr.left.first) { + state.tokens.curr.left.first.forEach(function (t) { + if (funct[t.value] === "const") { + error("E013", t, t.value); + } + }); + } else if (!left.left) { + warning("E031", that); + } else if (left.left.value === "arguments" && !state.directive["use strict"]) { + warning("E031", that); + } + that.right = expression(10); + return that; + } else if (left.identifier && !isReserved(left)) { + if (funct[left.value] === "exception") { + warning("W022", left); + } + that.right = expression(10); + return that; + } + + if (left === state.syntax["function"]) { + warning("W023", state.tokens.curr); + } + } + + error("E031", that); + }, p); + + x.exps = true; + x.assign = true; + return x; + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === "function") ? f : function (left) { + if (state.option.bitwise) { + warning("W016", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + return assignop(s, function (left, that) { + if (state.option.bitwise) { + warning("W016", that, that.id); + } + nonadjacent(state.tokens.prev, state.tokens.curr); + nonadjacent(state.tokens.curr, state.tokens.next); + if (left) { + if (left.id === "." || left.id === "[" || + (left.identifier && !isReserved(left))) { + expression(10); + return that; + } + if (left === state.syntax["function"]) { + warning("W023", state.tokens.curr); + } + return that; + } + error("E031", that); + }, 20); + } + + + function suffix(s) { + var x = symbol(s, 150); + + x.led = function (left) { + if (state.option.plusplus) { + warning("W016", this, this.id); + } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") { + warning("W017", this); + } + + this.left = left; + return this; + }; + return x; + } + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + // prop means that this identifier is that of an object property + + function optionalidentifier(fnparam, prop) { + if (!state.tokens.next.identifier) { + return; + } + + advance(); + + var curr = state.tokens.curr; + var val = state.tokens.curr.value; + + if (!isReserved(curr)) { + return val; + } + + if (prop) { + if (state.option.inES5()) { + return val; + } + } + + if (fnparam && val === "undefined") { + return val; + } + + // Display an info message about reserved words as properties + // and ES5 but do it only once. + if (prop && !api.getCache("displayed:I002")) { + api.setCache("displayed:I002", true); + warning("I002"); + } + + warning("W024", state.tokens.curr, state.tokens.curr.id); + return val; + } + + // fnparam means that this identifier is being defined as a function + // argument + // prop means that this identifier is that of an object property + function identifier(fnparam, prop) { + var i = optionalidentifier(fnparam, prop); + if (i) { + return i; + } + if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") { + warning("W025"); + } else { + error("E030", state.tokens.next, state.tokens.next.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (state.tokens.next.id !== ";" || noreach) { + return; + } + for (;;) { + do { + t = peek(i); + i += 1; + } while (t.id != "(end)" && t.id === "(comment)"); + + if (t.reach) { + return; + } + if (t.id !== "(endline)") { + if (t.id === "function") { + if (!state.option.latedef) { + break; + } + + warning("W026", t); + break; + } + + warning("W027", t, t.value, s); + break; + } + } + } + + + function statement(noindent) { + var values; + var i = indent, r, s = scope, t = state.tokens.next; + + if (t.id === ";") { + advance(";"); + return; + } + + // Is this a labelled statement? + var res = isReserved(t); + + // We're being more tolerant here: if someone uses + // a FutureReservedWord as a label, we warn but proceed + // anyway. + + if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") { + warning("W024", t, t.id); + res = false; + } + + // detect a destructuring assignment + if (_.has(["[", "{"], t.value)) { + if (lookupBlockType().isDestAssign) { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring expression"); + } + values = destructuringExpression(); + values.forEach(function (tok) { + isundef(funct, "W117", tok.token, tok.id); + }); + advance("="); + destructuringExpressionMatch(values, expression(10, true)); + advance(";"); + return; + } + } + if (t.identifier && !res && peek().id === ":") { + advance(); + advance(":"); + scope = Object.create(s); + addlabel(t.value, "label"); + + if (!state.tokens.next.labelled && state.tokens.next.value !== "{") { + warning("W028", state.tokens.next, t.value, state.tokens.next.value); + } + + state.tokens.next.label = t.value; + t = state.tokens.next; + } + + // Is it a lonely block? + + if (t.id === "{") { + block(true, true); + return; + } + + // Parse the statement. + + if (!noindent) { + indentation(); + } + r = expression(0, true); + + // Look for the final semicolon. + + if (!t.block) { + if (!state.option.expr && (!r || !r.exps)) { + warning("W030", state.tokens.curr); + } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") { + warning("W031", t); + } + + if (state.tokens.next.id !== ";") { + if (!state.option.asi) { + // If this is the last statement in a block that ends on + // the same line *and* option lastsemic is on, ignore the warning. + // Otherwise, complain about missing semicolon. + if (!state.option.lastsemic || state.tokens.next.id !== "}" || + state.tokens.next.line !== state.tokens.curr.line) { + warningAt("W033", state.tokens.curr.line, state.tokens.curr.character); + } + } + } else { + adjacent(state.tokens.curr, state.tokens.next); + advance(";"); + nonadjacent(state.tokens.curr, state.tokens.next); + } + } + + // Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function statements(startLine) { + var a = [], p; + + while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") { + if (state.tokens.next.id === ";") { + p = peek(); + + if (!p || (p.id !== "(" && p.id !== "[")) { + warning("W032"); + } + + advance(";"); + } else { + a.push(statement(startLine === state.tokens.next.line)); + } + } + return a; + } + + + /* + * read all directives + * recognizes a simple form of asi, but always + * warns, if it is used + */ + function directives() { + var i, p, pn; + + for (;;) { + if (state.tokens.next.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i); + i = i + 1; + } while (pn.id === "(endline)"); + + if (pn.id !== ";") { + if (pn.id !== "(string)" && pn.id !== "(number)" && + pn.id !== "(regexp)" && pn.identifier !== true && + pn.id !== "}") { + break; + } + warning("W033", state.tokens.next); + } else { + p = pn; + } + } else if (p.id === "}") { + // Directive with no other statements, warn about missing semicolon + warning("W033", p); + } else if (p.id !== ";") { + break; + } + + indentation(); + advance(); + if (state.directive[state.tokens.curr.value]) { + warning("W034", state.tokens.curr, state.tokens.curr.value); + } + + if (state.tokens.curr.value === "use strict") { + if (!state.option["(explicitNewcap)"]) + state.option.newcap = true; + state.option.undef = true; + } + + // there's no directive negation, so always set to true + state.directive[state.tokens.curr.value] = true; + + if (p.id === ";") { + advance(";"); + } + continue; + } + break; + } + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + * isfunc - true if block is a function body + */ + function block(ordinary, stmt, isfunc, isfatarrow) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + + if (!ordinary || !state.option.funcscope) + scope = Object.create(scope); + + nonadjacent(state.tokens.curr, state.tokens.next); + t = state.tokens.next; + + var metrics = funct["(metrics)"]; + metrics.nestedBlockDepth += 1; + metrics.verifyMaxNestedBlockDepthPerFunction(); + + if (state.tokens.next.id === "{") { + advance("{"); + + // create a new block scope + funct["(blockscope)"].stack(); + + line = state.tokens.curr.line; + if (state.tokens.next.id !== "}") { + indent += state.option.indent; + while (!ordinary && state.tokens.next.from > indent) { + indent += state.option.indent; + } + + if (isfunc) { + m = {}; + for (d in state.directive) { + if (_.has(state.directive, d)) { + m[d] = state.directive[d]; + } + } + directives(); + + if (state.option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !state.directive["use strict"]) { + warning("E007"); + } + } + } + + a = statements(line); + + metrics.statementCount += a.length; + + if (isfunc) { + state.directive = m; + } + + indent -= state.option.indent; + if (line !== state.tokens.next.line) { + indentation(); + } + } else if (line !== state.tokens.next.line) { + indentation(); + } + advance("}", t); + + funct["(blockscope)"].unstack(); + + indent = old_indent; + } else if (!ordinary) { + if (isfunc) { + m = {}; + if (stmt && !isfatarrow && !state.option.inMoz(true)) { + error("W118", state.tokens.curr, "function closure expressions"); + } + + if (!stmt) { + for (d in state.directive) { + if (_.has(state.directive, d)) { + m[d] = state.directive[d]; + } + } + } + expression(10); + + if (state.option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !state.directive["use strict"]) { + warning("E007"); + } + } + } else { + error("E021", state.tokens.next, "{", state.tokens.next.value); + } + } else { + + // check to avoid let declaration not within a block + funct["(nolet)"] = true; + + if (!stmt || state.option.curly) { + warning("W116", state.tokens.next, "{", state.tokens.next.value); + } + + noreach = true; + indent += state.option.indent; + // test indentation only if statement is in new line + a = [statement(state.tokens.next.line === state.tokens.curr.line)]; + indent -= state.option.indent; + noreach = false; + + delete funct["(nolet)"]; + } + funct["(verb)"] = null; + if (!ordinary || !state.option.funcscope) scope = s; + inblock = b; + if (ordinary && state.option.noempty && (!a || a.length === 0)) { + warning("W035"); + } + metrics.nestedBlockDepth -= 1; + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== "boolean") { + warning("W036", state.tokens.curr, m); + } + if (typeof member[m] === "number") { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(tkn) { + var name = tkn.value, line = tkn.line, a = implied[name]; + if (typeof a === "function") { + a = false; + } + + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + + + // Build the syntax table by declaring the syntactic elements of the language. + + type("(number)", function () { + return this; + }); + + type("(string)", function () { + return this; + }); + + state.syntax["(identifier)"] = { + type: "(identifier)", + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + + if (typeof s === "function") { + // Protection against accidental inheritance. + s = undefined; + } else if (typeof s === "boolean") { + f = funct; + funct = functions[0]; + addlabel(v, "var"); + s = funct; + funct = f; + } + var block; + if (_.has(funct, "(blockscope)")) { + block = funct["(blockscope)"].getlabel(v); + } + + // The name is in scope and defined in the current function. + if (funct === s || block) { + // Change 'unused' to 'var', and reject labels. + // the name is in a block scope + switch (block ? block[v]["(type)"] : funct[v]) { + case "unused": + if (block) block[v]["(type)"] = "var"; + else funct[v] = "var"; + break; + case "unction": + if (block) block[v]["(type)"] = "function"; + else funct[v] = "function"; + this["function"] = true; + break; + case "function": + this["function"] = true; + break; + case "label": + warning("W037", state.tokens.curr, v); + break; + } + } else if (funct["(global)"]) { + // The name is not defined in the function. If we are in the global + // scope, then we have an undefined variable. + // + // Operators typeof and delete do not raise runtime errors even if + // the base object of a reference is null so no need to display warning + // if we're inside of typeof or delete. + + if (typeof predefined[v] !== "boolean") { + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === "typeof" || anonname === "delete") || + (state.tokens.next && (state.tokens.next.value === "." || + state.tokens.next.value === "["))) { + + // if we're in a list comprehension, variables are declared + // locally and used before being defined. So we check + // the presence of the given variable in the comp array + // before declaring it undefined. + + if (!funct["(comparray)"].check(v)) { + isundef(funct, "W117", state.tokens.curr, v); + } + } + } + + note_implied(state.tokens.curr); + } else { + // If the name is already defined in the current + // function, but not as outer, then there is a scope error. + + switch (funct[v]) { + case "closure": + case "function": + case "var": + case "unused": + warning("W038", state.tokens.curr, v); + break; + case "label": + warning("W037", state.tokens.curr, v); + break; + case "outer": + case "global": + break; + default: + // If the name is defined in an outer function, make an outer entry, + // and if it was unused, make it var. + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("W039", state.tokens.curr, v); + note_implied(state.tokens.curr); + } else if (typeof s !== "object") { + // Operators typeof and delete do not raise runtime errors even + // if the base object of a reference is null so no need to + // + // display warning if we're inside of typeof or delete. + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === "typeof" || anonname === "delete") || + (state.tokens.next && + (state.tokens.next.value === "." || state.tokens.next.value === "["))) { + + isundef(funct, "W117", state.tokens.curr, v); + } + funct[v] = true; + note_implied(state.tokens.curr); + } else { + switch (s[v]) { + case "function": + case "unction": + this["function"] = true; + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "var": + case "unused": + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "label": + warning("W037", state.tokens.curr, v); + } + } + } + } + return this; + }, + led: function () { + error("E033", state.tokens.next, state.tokens.next.value); + } + }; + + type("(regexp)", function () { + return this; + }); + + // ECMAScript parser + + delim("(endline)"); + delim("(begin)"); + delim("(end)").reach = true; + delim("(error)").reach = true; + delim("}").reach = true; + delim(")"); + delim("]"); + delim("\"").reach = true; + delim("'").reach = true; + delim(";"); + delim(":").reach = true; + delim("#"); + + reserve("else"); + reserve("case").reach = true; + reserve("catch"); + reserve("default").reach = true; + reserve("finally"); + reservevar("arguments", function (x) { + if (state.directive["use strict"] && funct["(global)"]) { + warning("E008", x); + } + }); + reservevar("eval"); + reservevar("false"); + reservevar("Infinity"); + reservevar("null"); + reservevar("this", function (x) { + if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] && + funct["(name)"].charAt(0) > "Z") || funct["(global)"])) { + warning("W040", x); + } + }); + reservevar("true"); + reservevar("undefined"); + + assignop("=", "assign", 20); + assignop("+=", "assignadd", 20); + assignop("-=", "assignsub", 20); + assignop("*=", "assignmult", 20); + assignop("/=", "assigndiv", 20).nud = function () { + error("E014"); + }; + assignop("%=", "assignmod", 20); + + bitwiseassignop("&=", "assignbitand", 20); + bitwiseassignop("|=", "assignbitor", 20); + bitwiseassignop("^=", "assignbitxor", 20); + bitwiseassignop("<<=", "assignshiftleft", 20); + bitwiseassignop(">>=", "assignshiftright", 20); + bitwiseassignop(">>>=", "assignshiftrightunsigned", 20); + infix(",", function (left, that) { + var expr; + that.exprs = [left]; + if (!comma({peek: true})) { + return that; + } + while (true) { + if (!(expr = expression(10))) { + break; + } + that.exprs.push(expr); + if (state.tokens.next.value !== "," || !comma()) { + break; + } + } + return that; + }, 10, true); + + infix("?", function (left, that) { + increaseComplexityCount(); + that.left = left; + that.right = expression(10); + advance(":"); + that["else"] = expression(10); + return that; + }, 30); + + var orPrecendence = 40; + infix("||", function (left, that) { + increaseComplexityCount(); + that.left = left; + that.right = expression(orPrecendence); + return that; + }, orPrecendence); + infix("&&", "and", 50); + bitwise("|", "bitor", 70); + bitwise("^", "bitxor", 80); + bitwise("&", "bitand", 90); + relation("==", function (left, right) { + var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null"); + + if (!eqnull && state.option.eqeqeq) + warning("W116", this, "===", "=="); + else if (isPoorRelation(left)) + warning("W041", this, "===", left.value); + else if (isPoorRelation(right)) + warning("W041", this, "===", right.value); + + return this; + }); + relation("==="); + relation("!=", function (left, right) { + var eqnull = state.option.eqnull && + (left.value === "null" || right.value === "null"); + + if (!eqnull && state.option.eqeqeq) { + warning("W116", this, "!==", "!="); + } else if (isPoorRelation(left)) { + warning("W041", this, "!==", left.value); + } else if (isPoorRelation(right)) { + warning("W041", this, "!==", right.value); + } + return this; + }); + relation("!=="); + relation("<"); + relation(">"); + relation("<="); + relation(">="); + bitwise("<<", "shiftleft", 120); + bitwise(">>", "shiftright", 120); + bitwise(">>>", "shiftrightunsigned", 120); + infix("in", "in", 120); + infix("instanceof", "instanceof", 120); + infix("+", function (left, that) { + var right = expression(130); + if (left && right && left.id === "(string)" && right.id === "(string)") { + left.value += right.value; + left.character = right.character; + if (!state.option.scripturl && reg.javascriptURL.test(left.value)) { + warning("W050", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix("+", "num"); + prefix("+++", function () { + warning("W007"); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("+++", function (left) { + warning("W007"); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { + warning("W006"); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("---", function (left) { + warning("W006"); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("*", "mult", 140); + infix("/", "div", 140); + infix("%", "mod", 140); + + suffix("++", "postinc"); + prefix("++", "preinc"); + state.syntax["++"].exps = true; + + suffix("--", "postdec"); + prefix("--", "predec"); + state.syntax["--"].exps = true; + prefix("delete", function () { + var p = expression(10); + if (!p || (p.id !== "." && p.id !== "[")) { + warning("W051"); + } + this.first = p; + return this; + }).exps = true; + + prefix("~", function () { + if (state.option.bitwise) { + warning("W052", this, "~"); + } + expression(150); + return this; + }); + + prefix("...", function () { + if (!state.option.inESNext()) { + warning("W104", this, "spread/rest operator"); + } + if (!state.tokens.next.identifier) { + error("E030", state.tokens.next, state.tokens.next.value); + } + expression(150); + return this; + }); + + prefix("!", function () { + this.right = expression(150); + this.arity = "unary"; + + if (!this.right) { // '!' followed by nothing? Give up. + quit("E041", this.line || 0); + } + + if (bang[this.right.id] === true) { + warning("W018", this, "!"); + } + return this; + }); + + prefix("typeof", "typeof"); + prefix("new", function () { + var c = expression(155), i; + if (c && c.id !== "function") { + if (c.identifier) { + c["new"] = true; + switch (c.value) { + case "Number": + case "String": + case "Boolean": + case "Math": + case "JSON": + warning("W053", state.tokens.prev, c.value); + break; + case "Function": + if (!state.option.evil) { + warning("W054"); + } + break; + case "Date": + case "RegExp": + break; + default: + if (c.id !== "function") { + i = c.value.substr(0, 1); + if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) { + warning("W055", state.tokens.curr); + } + } + } + } else { + if (c.id !== "." && c.id !== "[" && c.id !== "(") { + warning("W056", state.tokens.curr); + } + } + } else { + if (!state.option.supernew) + warning("W057", this); + } + adjacent(state.tokens.curr, state.tokens.next); + if (state.tokens.next.id !== "(" && !state.option.supernew) { + warning("W058", state.tokens.curr, state.tokens.curr.value); + } + this.first = c; + return this; + }); + state.syntax["new"].exps = true; + + prefix("void").exps = true; + + infix(".", function (left, that) { + adjacent(state.tokens.prev, state.tokens.curr); + nobreak(); + var m = identifier(false, true); + + if (typeof m === "string") { + countMember(m); + } + + that.left = left; + that.right = m; + + if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") { + warning("W001"); + } + + if (left && left.value === "arguments" && (m === "callee" || m === "caller")) { + if (state.option.noarg) + warning("W059", left, m); + else if (state.directive["use strict"]) + error("E008"); + } else if (!state.option.evil && left && left.value === "document" && + (m === "write" || m === "writeln")) { + warning("W060", left); + } + + if (!state.option.evil && (m === "eval" || m === "execScript")) { + warning("W061"); + } + + return that; + }, 160, true); + + infix("(", function (left, that) { + if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") { + nobreak(state.tokens.prev, state.tokens.curr); + } + + nospace(); + if (state.option.immed && left && !left.immed && left.id === "function") { + warning("W062"); + } + + var n = 0; + var p = []; + + if (left) { + if (left.type === "(identifier)") { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if ("Number String Boolean Date Object".indexOf(left.value) === -1) { + if (left.value === "Math") { + warning("W063", left); + } else if (state.option.newcap) { + warning("W064", left); + } + } + } + } + } + + if (state.tokens.next.id !== ")") { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + + advance(")"); + nospace(state.tokens.prev, state.tokens.curr); + + if (typeof left === "object") { + if (left.value === "parseInt" && n === 1) { + warning("W065", state.tokens.curr); + } + if (!state.option.evil) { + if (left.value === "eval" || left.value === "Function" || + left.value === "execScript") { + warning("W061", left); + + if (p[0] && [0].id === "(string)") { + addInternalSrc(left, p[0].value); + } + } else if (p[0] && p[0].id === "(string)" && + (left.value === "setTimeout" || + left.value === "setInterval")) { + warning("W066", left); + addInternalSrc(left, p[0].value); + + // window.setTimeout/setInterval + } else if (p[0] && p[0].id === "(string)" && + left.value === "." && + left.left.value === "window" && + (left.right === "setTimeout" || + left.right === "setInterval")) { + warning("W066", left); + addInternalSrc(left, p[0].value); + } + } + if (!left.identifier && left.id !== "." && left.id !== "[" && + left.id !== "(" && left.id !== "&&" && left.id !== "||" && + left.id !== "?") { + warning("W067", left); + } + } + + that.left = left; + return that; + }, 155, true).exps = true; + + prefix("(", function () { + nospace(); + var bracket, brackets = []; + var pn, pn1, i = 0; + var ret; + + do { + pn = peek(i); + i += 1; + pn1 = peek(i); + i += 1; + } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)"); + + if (state.tokens.next.id === "function") { + state.tokens.next.immed = true; + } + + var exprs = []; + + if (state.tokens.next.id !== ")") { + for (;;) { + if (pn1.value === "=>" && state.tokens.next.value === "{") { + bracket = state.tokens.next; + bracket.left = destructuringExpression(); + brackets.push(bracket); + for (var t in bracket.left) { + exprs.push(bracket.left[t].token); + } + } else { + exprs.push(expression(10)); + } + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + + advance(")", this); + nospace(state.tokens.prev, state.tokens.curr); + if (state.option.immed && exprs[0] && exprs[0].id === "function") { + if (state.tokens.next.id !== "(" && + (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) { + warning("W068", this); + } + } + + if (state.tokens.next.value === "=>") { + return exprs; + } + if (!exprs.length) { + return; + } + if (exprs.length > 1) { + ret = Object.create(state.syntax[","]); + ret.exprs = exprs; + } else { + ret = exprs[0]; + } + if (ret) { + ret.paren = true; + } + return ret; + }); + + application("=>"); + + infix("[", function (left, that) { + nobreak(state.tokens.prev, state.tokens.curr); + nospace(); + var e = expression(10), s; + if (e && e.type === "(string)") { + if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) { + warning("W061", that); + } + + countMember(e.value); + if (!state.option.sub && reg.identifier.test(e.value)) { + s = state.syntax[e.value]; + if (!s || !isReserved(s)) { + warning("W069", state.tokens.prev, e.value); + } + } + } + advance("]", that); + + if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") { + warning("W001"); + } + + nospace(state.tokens.prev, state.tokens.curr); + that.left = left; + that.right = e; + return that; + }, 160, true); + + function comprehensiveArrayExpression() { + var res = {}; + res.exps = true; + funct["(comparray)"].stack(); + + // Handle reversed for expressions, used in spidermonkey + var reversed = false; + if (state.tokens.next.value !== "for") { + reversed = true; + if (!state.option.inMoz(true)) { + warning("W116", state.tokens.next, "for", state.tokens.next.value); + } + funct["(comparray)"].setState("use"); + res.right = expression(10); + } + + advance("for"); + if (state.tokens.next.value === "each") { + advance("each"); + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "for each"); + } + } + advance("("); + funct["(comparray)"].setState("define"); + res.left = expression(130); + if (_.contains(["in", "of"], state.tokens.next.value)) { + advance(); + } else { + error("E045", state.tokens.curr); + } + funct["(comparray)"].setState("generate"); + expression(10); + + advance(")"); + if (state.tokens.next.value === "if") { + advance("if"); + advance("("); + funct["(comparray)"].setState("filter"); + res.filter = expression(10); + advance(")"); + } + + if (!reversed) { + funct["(comparray)"].setState("use"); + res.right = expression(10); + } + + advance("]"); + funct["(comparray)"].unstack(); + return res; + } + + prefix("[", function () { + var blocktype = lookupBlockType(true); + if (blocktype.isCompArray) { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "array comprehension"); + } + return comprehensiveArrayExpression(); + } else if (blocktype.isDestAssign && !state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring assignment"); + } + var b = state.tokens.curr.line !== state.tokens.next.line; + this.first = []; + if (b) { + indent += state.option.indent; + if (state.tokens.next.from === indent + state.option.indent) { + indent += state.option.indent; + } + } + while (state.tokens.next.id !== "(end)") { + while (state.tokens.next.id === ",") { + if (!state.option.inES5()) + warning("W070"); + advance(","); + } + if (state.tokens.next.id === "]") { + break; + } + if (b && state.tokens.curr.line !== state.tokens.next.line) { + indentation(); + } + this.first.push(expression(10)); + if (state.tokens.next.id === ",") { + comma({ allowTrailing: true }); + if (state.tokens.next.id === "]" && !state.option.inES5(true)) { + warning("W070", state.tokens.curr); + break; + } + } else { + break; + } + } + if (b) { + indent -= state.option.indent; + indentation(); + } + advance("]", this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(false, true); + + if (!id) { + if (state.tokens.next.id === "(string)") { + id = state.tokens.next.value; + advance(); + } else if (state.tokens.next.id === "(number)") { + id = state.tokens.next.value.toString(); + advance(); + } + } + + if (id === "hasOwnProperty") { + warning("W001"); + } + + return id; + } + + + function functionparams(parsed) { + var curr, next; + var params = []; + var ident; + var tokens = []; + var t; + var pastDefault = false; + + if (parsed) { + if (parsed instanceof Array) { + for (var i in parsed) { + curr = parsed[i]; + if (_.contains(["{", "["], curr.id)) { + for (t in curr.left) { + t = tokens[t]; + if (t.id) { + params.push(t.id); + addlabel(t.id, "unused", t.token); + } + } + } else if (curr.value === "...") { + if (!state.option.inESNext()) { + warning("W104", curr, "spread/rest operator"); + } + continue; + } else { + addlabel(curr.value, "unused", curr); + } + } + return params; + } else { + if (parsed.identifier === true) { + addlabel(parsed.value, "unused", parsed); + return [parsed]; + } + } + } + + next = state.tokens.next; + + advance("("); + nospace(); + + if (state.tokens.next.id === ")") { + advance(")"); + return; + } + + for (;;) { + if (_.contains(["{", "["], state.tokens.next.id)) { + tokens = destructuringExpression(); + for (t in tokens) { + t = tokens[t]; + if (t.id) { + params.push(t.id); + addlabel(t.id, "unused", t.token); + } + } + } else if (state.tokens.next.value === "...") { + if (!state.option.inESNext()) { + warning("W104", state.tokens.next, "spread/rest operator"); + } + advance("..."); + nospace(); + ident = identifier(true); + params.push(ident); + addlabel(ident, "unused", state.tokens.curr); + } else { + ident = identifier(true); + params.push(ident); + addlabel(ident, "unused", state.tokens.curr); + } + + // it is a syntax error to have a regular argument after a default argument + if (pastDefault) { + if (state.tokens.next.id !== "=") { + error("E051", state.tokens.current); + } + } + if (state.tokens.next.id === "=") { + if (!state.option.inESNext()) { + warning("W119", state.tokens.next, "default parameters"); + } + advance("="); + pastDefault = true; + expression(10); + } + if (state.tokens.next.id === ",") { + comma(); + } else { + advance(")", next); + nospace(state.tokens.prev, state.tokens.curr); + return params; + } + } + } + + + function doFunction(name, statement, generator, fatarrowparams) { + var f; + var oldOption = state.option; + var oldIgnored = state.ignored; + var oldScope = scope; + + state.option = Object.create(state.option); + state.ignored = Object.create(state.ignored); + scope = Object.create(scope); + + funct = { + "(name)" : name || "\"" + anonname + "\"", + "(line)" : state.tokens.next.line, + "(character)" : state.tokens.next.character, + "(context)" : funct, + "(breakage)" : 0, + "(loopage)" : 0, + "(metrics)" : createMetrics(state.tokens.next), + "(scope)" : scope, + "(statement)" : statement, + "(tokens)" : {}, + "(blockscope)": funct["(blockscope)"], + "(comparray)" : funct["(comparray)"] + }; + + if (generator) { + funct["(generator)"] = true; + } + + f = funct; + state.tokens.curr.funct = funct; + + functions.push(funct); + + if (name) { + addlabel(name, "function"); + } + + funct["(params)"] = functionparams(fatarrowparams); + funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]); + + block(false, true, true, fatarrowparams ? true:false); + + if (generator && funct["(generator)"] !== "yielded") { + error("E047", state.tokens.curr); + } + + funct["(metrics)"].verifyMaxStatementsPerFunction(); + funct["(metrics)"].verifyMaxComplexityPerFunction(); + funct["(unusedOption)"] = state.option.unused; + + scope = oldScope; + state.option = oldOption; + state.ignored = oldIgnored; + funct["(last)"] = state.tokens.curr.line; + funct["(lastcharacter)"] = state.tokens.curr.character; + funct = funct["(context)"]; + + return f; + } + + function createMetrics(functionStartToken) { + return { + statementCount: 0, + nestedBlockDepth: -1, + ComplexityCount: 1, + + verifyMaxStatementsPerFunction: function () { + if (state.option.maxstatements && + this.statementCount > state.option.maxstatements) { + warning("W071", functionStartToken, this.statementCount); + } + }, + + verifyMaxParametersPerFunction: function (params) { + params = params || []; + + if (state.option.maxparams && params.length > state.option.maxparams) { + warning("W072", functionStartToken, params.length); + } + }, + + verifyMaxNestedBlockDepthPerFunction: function () { + if (state.option.maxdepth && + this.nestedBlockDepth > 0 && + this.nestedBlockDepth === state.option.maxdepth + 1) { + warning("W073", null, this.nestedBlockDepth); + } + }, + + verifyMaxComplexityPerFunction: function () { + var max = state.option.maxcomplexity; + var cc = this.ComplexityCount; + if (max && cc > max) { + warning("W074", functionStartToken, cc); + } + } + }; + } + + function increaseComplexityCount() { + funct["(metrics)"].ComplexityCount += 1; + } + + // Parse assignments that were found instead of conditionals. + // For example: if (a = 1) { ... } + + function checkCondAssignment(expr) { + var id, paren; + if (expr) { + id = expr.id; + paren = expr.paren; + if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) { + id = expr.id; + paren = paren || expr.paren; + } + } + switch (id) { + case "=": + case "+=": + case "-=": + case "*=": + case "%=": + case "&=": + case "|=": + case "^=": + case "/=": + if (!paren && !state.option.boss) { + warning("W084"); + } + } + } + + + (function (x) { + x.nud = function (isclassdef) { + var b, f, i, p, t, g; + var props = {}; // All properties, including accessors + var tag = ""; + + function saveProperty(name, tkn) { + if (props[name] && _.has(props, name)) + warning("W075", state.tokens.next, i); + else + props[name] = {}; + + props[name].basic = true; + props[name].basictkn = tkn; + } + + function saveSetter(name, tkn) { + if (props[name] && _.has(props, name)) { + if (props[name].basic || props[name].setter) + warning("W075", state.tokens.next, i); + } else { + props[name] = {}; + } + + props[name].setter = true; + props[name].setterToken = tkn; + } + + function saveGetter(name) { + if (props[name] && _.has(props, name)) { + if (props[name].basic || props[name].getter) + warning("W075", state.tokens.next, i); + } else { + props[name] = {}; + } + + props[name].getter = true; + props[name].getterToken = state.tokens.curr; + } + + b = state.tokens.curr.line !== state.tokens.next.line; + if (b) { + indent += state.option.indent; + if (state.tokens.next.from === indent + state.option.indent) { + indent += state.option.indent; + } + } + + for (;;) { + if (state.tokens.next.id === "}") { + break; + } + + if (b) { + indentation(); + } + + if (isclassdef && state.tokens.next.value === "static") { + advance("static"); + tag = "static "; + } + + if (state.tokens.next.value === "get" && peek().id !== ":") { + advance("get"); + + if (!state.option.inES5(!isclassdef)) { + error("E034"); + } + + i = property_name(); + if (!i) { + error("E035"); + } + + // It is a Syntax Error if PropName of MethodDefinition is + // "constructor" and SpecialMethod of MethodDefinition is true. + if (isclassdef && i === "constructor") { + error("E049", state.tokens.next, "class getter method", i); + } + + saveGetter(tag + i); + t = state.tokens.next; + adjacent(state.tokens.curr, state.tokens.next); + f = doFunction(); + p = f["(params)"]; + + if (p) { + warning("W076", t, p[0], i); + } + + adjacent(state.tokens.curr, state.tokens.next); + } else if (state.tokens.next.value === "set" && peek().id !== ":") { + advance("set"); + + if (!state.option.inES5(!isclassdef)) { + error("E034"); + } + + i = property_name(); + if (!i) { + error("E035"); + } + + // It is a Syntax Error if PropName of MethodDefinition is + // "constructor" and SpecialMethod of MethodDefinition is true. + if (isclassdef && i === "constructor") { + error("E049", state.tokens.next, "class setter method", i); + } + + saveSetter(tag + i, state.tokens.next); + t = state.tokens.next; + adjacent(state.tokens.curr, state.tokens.next); + f = doFunction(); + p = f["(params)"]; + + if (!p || p.length !== 1) { + warning("W077", t, i); + } + } else { + g = false; + if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") { + if (!state.option.inESNext()) { + warning("W104", state.tokens.next, "generator functions"); + } + advance("*"); + g = true; + } + i = property_name(); + saveProperty(tag + i, state.tokens.next); + + if (typeof i !== "string") { + break; + } + + if (state.tokens.next.value === "(") { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "concise methods"); + } + doFunction(i, undefined, g); + } else if (!isclassdef) { + advance(":"); + nonadjacent(state.tokens.curr, state.tokens.next); + expression(10); + } + } + // It is a Syntax Error if PropName of MethodDefinition is "prototype". + if (isclassdef && i === "prototype") { + error("E049", state.tokens.next, "class method", i); + } + + countMember(i); + if (isclassdef) { + tag = ""; + continue; + } + if (state.tokens.next.id === ",") { + comma({ allowTrailing: true, property: true }); + if (state.tokens.next.id === ",") { + warning("W070", state.tokens.curr); + } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) { + warning("W070", state.tokens.curr); + } + } else { + break; + } + } + if (b) { + indent -= state.option.indent; + indentation(); + } + advance("}", this); + + // Check for lonely setters if in the ES5 mode. + if (state.option.inES5()) { + for (var name in props) { + if (_.has(props, name) && props[name].setter && !props[name].getter) { + warning("W078", props[name].setterToken); + } + } + } + return this; + }; + x.fud = function () { + error("E036", state.tokens.curr); + }; + }(delim("{"))); + + function destructuringExpression() { + var id, ids; + var identifiers = []; + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring expression"); + } + var nextInnerDE = function () { + var ident; + if (_.contains(["[", "{"], state.tokens.next.value)) { + ids = destructuringExpression(); + for (var id in ids) { + id = ids[id]; + identifiers.push({ id: id.id, token: id.token }); + } + } else if (state.tokens.next.value === ",") { + identifiers.push({ id: null, token: state.tokens.curr }); + } else { + ident = identifier(); + if (ident) + identifiers.push({ id: ident, token: state.tokens.curr }); + } + }; + if (state.tokens.next.value === "[") { + advance("["); + nextInnerDE(); + while (state.tokens.next.value !== "]") { + advance(","); + nextInnerDE(); + } + advance("]"); + } else if (state.tokens.next.value === "{") { + advance("{"); + id = identifier(); + if (state.tokens.next.value === ":") { + advance(":"); + nextInnerDE(); + } else { + identifiers.push({ id: id, token: state.tokens.curr }); + } + while (state.tokens.next.value !== "}") { + advance(","); + id = identifier(); + if (state.tokens.next.value === ":") { + advance(":"); + nextInnerDE(); + } else { + identifiers.push({ id: id, token: state.tokens.curr }); + } + } + advance("}"); + } + return identifiers; + } + function destructuringExpressionMatch(tokens, value) { + if (value.first) { + _.zip(tokens, value.first).forEach(function (val) { + var token = val[0]; + var value = val[1]; + if (token && value) { + token.first = value; + } else if (token && token.first && !value) { + warning("W080", token.first, token.first.value); + } /* else { + XXX value is discarded: wouldn't it need a warning ? + } */ + }); + } + } + + var conststatement = stmt("const", function (prefix) { + var tokens, value; + // state variable to know if it is a lone identifier, or a destructuring statement. + var lone; + + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "const"); + } + + this.first = []; + for (;;) { + var names = []; + nonadjacent(state.tokens.curr, state.tokens.next); + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr } ]; + lone = true; + } + for (var t in tokens) { + t = tokens[t]; + if (funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id) { + addlabel(t.id, "const"); + names.push(t.token); + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id !== "=") { + warning("E012", state.tokens.curr, state.tokens.curr.value); + } + + if (state.tokens.next.id === "=") { + nonadjacent(state.tokens.curr, state.tokens.next); + advance("="); + nonadjacent(state.tokens.curr, state.tokens.next); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + return this; + }); + conststatement.exps = true; + var varstatement = stmt("var", function (prefix) { + // JavaScript does not have block scope. It only has function scope. So, + // declaring a variable in a block can have unexpected consequences. + var tokens, lone, value; + + if (funct["(onevar)"] && state.option.onevar) { + warning("W081"); + } else if (!funct["(global)"]) { + funct["(onevar)"] = true; + } + + this.first = []; + for (;;) { + var names = []; + nonadjacent(state.tokens.curr, state.tokens.next); + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr } ]; + lone = true; + } + for (var t in tokens) { + t = tokens[t]; + if (state.option.inESNext() && funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id) { + addlabel(t.id, "unused", t.token); + names.push(t.token); + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id === "=") { + nonadjacent(state.tokens.curr, state.tokens.next); + advance("="); + nonadjacent(state.tokens.curr, state.tokens.next); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + var letstatement = stmt("let", function (prefix) { + var tokens, lone, value, letblock; + + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "let"); + } + + if (state.tokens.next.value === "(") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.next, "let block"); + } + advance("("); + funct["(blockscope)"].stack(); + letblock = true; + } else if (funct["(nolet)"]) { + error("E048", state.tokens.curr); + } + + if (funct["(onevar)"] && state.option.onevar) { + warning("W081"); + } else if (!funct["(global)"]) { + funct["(onevar)"] = true; + } + + this.first = []; + for (;;) { + var names = []; + nonadjacent(state.tokens.curr, state.tokens.next); + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr.value } ]; + lone = true; + } + for (var t in tokens) { + t = tokens[t]; + if (state.option.inESNext() && funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id && !funct["(nolet)"]) { + addlabel(t.id, "unused", t.token, true); + names.push(t.token); + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id === "=") { + nonadjacent(state.tokens.curr, state.tokens.next); + advance("="); + nonadjacent(state.tokens.curr, state.tokens.next); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + if (letblock) { + advance(")"); + block(true, true); + this.block = true; + funct["(blockscope)"].unstack(); + } + + return this; + }); + letstatement.exps = true; + + blockstmt("class", function () { + return classdef.call(this, true); + }); + + function classdef(stmt) { + /*jshint validthis:true */ + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "class"); + } + if (stmt) { + // BindingIdentifier + this.name = identifier(); + addlabel(this.name, "unused", state.tokens.curr); + } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") { + // BindingIdentifier(opt) + this.name = identifier(); + } + classtail(this); + return this; + } + + function classtail(c) { + var strictness = state.directive["use strict"]; + + // ClassHeritage(opt) + if (state.tokens.next.value === "extends") { + advance("extends"); + c.heritage = expression(10); + } + + // A ClassBody is always strict code. + state.directive["use strict"] = true; + advance("{"); + // ClassBody(opt) + c.body = state.syntax["{"].nud(true); + state.directive["use strict"] = strictness; + } + + blockstmt("function", function () { + var generator = false; + if (state.tokens.next.value === "*") { + advance("*"); + if (state.option.inESNext(true)) { + generator = true; + } else { + warning("W119", state.tokens.curr, "function*"); + } + } + if (inblock) { + warning("W082", state.tokens.curr); + + } + var i = identifier(); + if (funct[i] === "const") { + warning("E011", null, i); + } + adjacent(state.tokens.curr, state.tokens.next); + addlabel(i, "unction", state.tokens.curr); + + doFunction(i, { statement: true }, generator); + if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) { + error("E039"); + } + return this; + }); + + prefix("function", function () { + var generator = false; + if (state.tokens.next.value === "*") { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "function*"); + } + advance("*"); + generator = true; + } + var i = optionalidentifier(); + if (i || state.option.gcl) { + adjacent(state.tokens.curr, state.tokens.next); + } else { + nonadjacent(state.tokens.curr, state.tokens.next); + } + doFunction(i, undefined, generator); + if (!state.option.loopfunc && funct["(loopage)"]) { + warning("W083"); + } + return this; + }); + + blockstmt("if", function () { + var t = state.tokens.next; + increaseComplexityCount(); + state.condition = true; + advance("("); + nonadjacent(this, t); + nospace(); + checkCondAssignment(expression(0)); + advance(")", t); + state.condition = false; + nospace(state.tokens.prev, state.tokens.curr); + block(true, true); + if (state.tokens.next.id === "else") { + nonadjacent(state.tokens.curr, state.tokens.next); + advance("else"); + if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt("try", function () { + var b; + + function doCatch() { + var oldScope = scope; + var e; + + advance("catch"); + nonadjacent(state.tokens.curr, state.tokens.next); + advance("("); + + scope = Object.create(oldScope); + + e = state.tokens.next.value; + if (state.tokens.next.type !== "(identifier)") { + e = null; + warning("E030", state.tokens.next, e); + } + + advance(); + + funct = { + "(name)" : "(catch)", + "(line)" : state.tokens.next.line, + "(character)": state.tokens.next.character, + "(context)" : funct, + "(breakage)" : funct["(breakage)"], + "(loopage)" : funct["(loopage)"], + "(scope)" : scope, + "(statement)": false, + "(metrics)" : createMetrics(state.tokens.next), + "(catch)" : true, + "(tokens)" : {}, + "(blockscope)": funct["(blockscope)"], + "(comparray)": funct["(comparray)"] + }; + + if (e) { + addlabel(e, "exception"); + } + + if (state.tokens.next.value === "if") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "catch filter"); + } + advance("if"); + expression(0); + } + + advance(")"); + + state.tokens.curr.funct = funct; + functions.push(funct); + + block(false); + + scope = oldScope; + + funct["(last)"] = state.tokens.curr.line; + funct["(lastcharacter)"] = state.tokens.curr.character; + funct = funct["(context)"]; + } + + block(false); + + while (state.tokens.next.id === "catch") { + increaseComplexityCount(); + if (b && (!state.option.inMoz(true))) { + warning("W118", state.tokens.next, "multiple catch blocks"); + } + doCatch(); + b = true; + } + + if (state.tokens.next.id === "finally") { + advance("finally"); + block(false); + return; + } + + if (!b) { + error("E021", state.tokens.next, "catch", state.tokens.next.value); + } + + return this; + }); + + blockstmt("while", function () { + var t = state.tokens.next; + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); + nonadjacent(this, t); + nospace(); + checkCondAssignment(expression(0)); + advance(")", t); + nospace(state.tokens.prev, state.tokens.curr); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }).labelled = true; + + blockstmt("with", function () { + var t = state.tokens.next; + if (state.directive["use strict"]) { + error("E010", state.tokens.curr); + } else if (!state.option.withstmt) { + warning("W085", state.tokens.curr); + } + + advance("("); + nonadjacent(this, t); + nospace(); + expression(0); + advance(")", t); + nospace(state.tokens.prev, state.tokens.curr); + block(true, true); + + return this; + }); + + blockstmt("switch", function () { + var t = state.tokens.next, + g = false; + funct["(breakage)"] += 1; + advance("("); + nonadjacent(this, t); + nospace(); + checkCondAssignment(expression(0)); + advance(")", t); + nospace(state.tokens.prev, state.tokens.curr); + nonadjacent(state.tokens.curr, state.tokens.next); + t = state.tokens.next; + advance("{"); + nonadjacent(state.tokens.curr, state.tokens.next); + indent += state.option.indent; + this.cases = []; + + for (;;) { + switch (state.tokens.next.id) { + case "case": + switch (funct["(verb)"]) { + case "yield": + case "break": + case "case": + case "continue": + case "return": + case "switch": + case "throw": + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) { + warning("W086", state.tokens.curr, "case"); + } + } + indentation(-state.option.indent); + advance("case"); + this.cases.push(expression(20)); + increaseComplexityCount(); + g = true; + advance(":"); + funct["(verb)"] = "case"; + break; + case "default": + switch (funct["(verb)"]) { + case "yield": + case "break": + case "continue": + case "return": + case "throw": + break; + default: + // Do not display a warning if 'default' is the first statement or if + // there is a special /* falls through */ comment. + if (this.cases.length) { + if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) { + warning("W086", state.tokens.curr, "default"); + } + } + } + indentation(-state.option.indent); + advance("default"); + g = true; + advance(":"); + break; + case "}": + indent -= state.option.indent; + indentation(); + advance("}", t); + funct["(breakage)"] -= 1; + funct["(verb)"] = undefined; + return; + case "(end)": + error("E023", state.tokens.next, "}"); + return; + default: + if (g) { + switch (state.tokens.curr.id) { + case ",": + error("E040"); + return; + case ":": + g = false; + statements(); + break; + default: + error("E025", state.tokens.curr); + return; + } + } else { + if (state.tokens.curr.id === ":") { + advance(":"); + error("E024", state.tokens.curr, ":"); + statements(); + } else { + error("E021", state.tokens.next, "case", state.tokens.next.value); + return; + } + } + } + } + }).labelled = true; + + stmt("debugger", function () { + if (!state.option.debug) { + warning("W087", this); + } + return this; + }).exps = true; + + (function () { + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + + this.first = block(true, true); + advance("while"); + var t = state.tokens.next; + nonadjacent(state.tokens.curr, t); + advance("("); + nospace(); + checkCondAssignment(expression(0)); + advance(")", t); + nospace(state.tokens.prev, state.tokens.curr); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt("for", function () { + var s, t = state.tokens.next; + var letscope = false; + var foreachtok = null; + + if (t.value === "each") { + foreachtok = t; + advance("each"); + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "for each"); + } + } + + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); + nonadjacent(this, t); + nospace(); + + // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)? + var nextop; // contains the token of the "in" or "of" operator + var i = 0; + var inof = ["in", "of"]; + do { + nextop = peek(i); + ++i; + } while (!_.contains(inof, nextop.value) && nextop.value !== ";" && + nextop.type !== "(end)"); + + // if we're in a for (… in|of …) statement + if (_.contains(inof, nextop.value)) { + if (!state.option.inESNext() && nextop.value === "of") { + error("W104", nextop, "for of"); + } + if (state.tokens.next.id === "var") { + advance("var"); + state.syntax["var"].fud.call(state.syntax["var"].fud, true); + } else if (state.tokens.next.id === "let") { + advance("let"); + // create a new block scope + letscope = true; + funct["(blockscope)"].stack(); + state.syntax["let"].fud.call(state.syntax["let"].fud, true); + } else { + switch (funct[state.tokens.next.value]) { + case "unused": + funct[state.tokens.next.value] = "var"; + break; + case "var": + break; + default: + if (!funct["(blockscope)"].getlabel(state.tokens.next.value)) + warning("W088", state.tokens.next, state.tokens.next.value); + } + advance(); + } + advance(nextop.value); + expression(20); + advance(")", t); + s = block(true, true); + if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" || + s[0].value !== "if")) { + warning("W089", this); + } + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + } else { + if (foreachtok) { + error("E045", foreachtok); + } + if (state.tokens.next.id !== ";") { + if (state.tokens.next.id === "var") { + advance("var"); + state.syntax["var"].fud.call(state.syntax["var"].fud); + } else if (state.tokens.next.id === "let") { + advance("let"); + // create a new block scope + letscope = true; + funct["(blockscope)"].stack(); + state.syntax["let"].fud.call(state.syntax["let"].fud); + } else { + for (;;) { + expression(0, "for"); + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + } + nolinebreak(state.tokens.curr); + advance(";"); + if (state.tokens.next.id !== ";") { + checkCondAssignment(expression(0)); + } + nolinebreak(state.tokens.curr); + advance(";"); + if (state.tokens.next.id === ";") { + error("E021", state.tokens.next, ")", ";"); + } + if (state.tokens.next.id !== ")") { + for (;;) { + expression(0, "for"); + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + advance(")", t); + nospace(state.tokens.prev, state.tokens.curr); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + + } + // unstack loop blockscope + if (letscope) { + funct["(blockscope)"].unstack(); + } + return this; + }).labelled = true; + + + stmt("break", function () { + var v = state.tokens.next.value; + + if (funct["(breakage)"] === 0) + warning("W052", state.tokens.next, this.value); + + if (!state.option.asi) + nolinebreak(this); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + if (state.tokens.curr.line === state.tokens.next.line) { + if (funct[v] !== "label") { + warning("W090", state.tokens.next, v); + } else if (scope[v] !== funct) { + warning("W091", state.tokens.next, v); + } + this.first = state.tokens.next; + advance(); + } + } + reachable("break"); + return this; + }).exps = true; + + + stmt("continue", function () { + var v = state.tokens.next.value; + + if (funct["(breakage)"] === 0) + warning("W052", state.tokens.next, this.value); + + if (!state.option.asi) + nolinebreak(this); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + if (state.tokens.curr.line === state.tokens.next.line) { + if (funct[v] !== "label") { + warning("W090", state.tokens.next, v); + } else if (scope[v] !== funct) { + warning("W091", state.tokens.next, v); + } + this.first = state.tokens.next; + advance(); + } + } else if (!funct["(loopage)"]) { + warning("W052", state.tokens.next, this.value); + } + reachable("continue"); + return this; + }).exps = true; + + + stmt("return", function () { + if (this.line === state.tokens.next.line) { + if (state.tokens.next.id === "(regexp)") + warning("W092"); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + nonadjacent(state.tokens.curr, state.tokens.next); + this.first = expression(0); + + if (this.first && + this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) { + warningAt("W093", this.first.line, this.first.character); + } + } + } else { + if (state.tokens.next.type === "(punctuator)" && + ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) { + nolinebreak(this); // always warn (Line breaking error) + } + } + reachable("return"); + return this; + }).exps = true; + + (function (x) { + x.exps = true; + x.lbp = 25; + }(prefix("yield", function () { + var prev = state.tokens.prev; + if (state.option.inESNext(true) && !funct["(generator)"]) { + error("E046", state.tokens.curr, "yield"); + } else if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "yield"); + } + funct["(generator)"] = "yielded"; + if (this.line === state.tokens.next.line || !state.option.inMoz(true)) { + if (state.tokens.next.id === "(regexp)") + warning("W092"); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach && state.tokens.next.nud) { + nobreaknonadjacent(state.tokens.curr, state.tokens.next); + this.first = expression(10); + + if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) { + warningAt("W093", this.first.line, this.first.character); + } + } + + if (state.option.inMoz(true) && state.tokens.next.id !== ")" && + (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) { + error("E050", this); + } + } else if (!state.option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + return this; + }))); + + + stmt("throw", function () { + nolinebreak(this); + nonadjacent(state.tokens.curr, state.tokens.next); + this.first = expression(20); + reachable("throw"); + return this; + }).exps = true; + + stmt("import", function () { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "import"); + } + + if (state.tokens.next.identifier) { + this.name = identifier(); + addlabel(this.name, "unused", state.tokens.curr); + } else { + advance("{"); + for (;;) { + var importName; + if (state.tokens.next.type === "default") { + importName = "default"; + advance("default"); + } else { + importName = identifier(); + } + if (state.tokens.next.value === "as") { + advance("as"); + importName = identifier(); + } + addlabel(importName, "unused", state.tokens.curr); + + if (state.tokens.next.value === ",") { + advance(","); + } else if (state.tokens.next.value === "}") { + advance("}"); + break; + } else { + error("E024", state.tokens.next, state.tokens.next.value); + break; + } + } + } + + advance("from"); + advance("(string)"); + return this; + }).exps = true; + + stmt("export", function () { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "export"); + } + + if (state.tokens.next.type === "default") { + advance("default"); + if (state.tokens.next.id === "function" || state.tokens.next.id === "class") { + this.block = true; + } + this.exportee = expression(10); + + return this; + } + + if (state.tokens.next.value === "{") { + advance("{"); + for (;;) { + identifier(); + + if (state.tokens.next.value === ",") { + advance(","); + } else if (state.tokens.next.value === "}") { + advance("}"); + break; + } else { + error("E024", state.tokens.next, state.tokens.next.value); + break; + } + } + return this; + } + + if (state.tokens.next.id === "var") { + advance("var"); + state.syntax["var"].fud.call(state.syntax["var"].fud); + } else if (state.tokens.next.id === "let") { + advance("let"); + state.syntax["let"].fud.call(state.syntax["let"].fud); + } else if (state.tokens.next.id === "const") { + advance("const"); + state.syntax["const"].fud.call(state.syntax["const"].fud); + } else if (state.tokens.next.id === "function") { + this.block = true; + advance("function"); + state.syntax["function"].fud(); + } else if (state.tokens.next.id === "class") { + this.block = true; + advance("class"); + state.syntax["class"].fud(); + } else { + error("E024", state.tokens.next, state.tokens.next.value); + } + + return this; + }).exps = true; + + // Future Reserved Words + + FutureReservedWord("abstract"); + FutureReservedWord("boolean"); + FutureReservedWord("byte"); + FutureReservedWord("char"); + FutureReservedWord("class", { es5: true, nud: classdef }); + FutureReservedWord("double"); + FutureReservedWord("enum", { es5: true }); + FutureReservedWord("export", { es5: true }); + FutureReservedWord("extends", { es5: true }); + FutureReservedWord("final"); + FutureReservedWord("float"); + FutureReservedWord("goto"); + FutureReservedWord("implements", { es5: true, strictOnly: true }); + FutureReservedWord("import", { es5: true }); + FutureReservedWord("int"); + FutureReservedWord("interface", { es5: true, strictOnly: true }); + FutureReservedWord("long"); + FutureReservedWord("native"); + FutureReservedWord("package", { es5: true, strictOnly: true }); + FutureReservedWord("private", { es5: true, strictOnly: true }); + FutureReservedWord("protected", { es5: true, strictOnly: true }); + FutureReservedWord("public", { es5: true, strictOnly: true }); + FutureReservedWord("short"); + FutureReservedWord("static", { es5: true, strictOnly: true }); + FutureReservedWord("super", { es5: true }); + FutureReservedWord("synchronized"); + FutureReservedWord("throws"); + FutureReservedWord("transient"); + FutureReservedWord("volatile"); + + // this function is used to determine wether a squarebracket or a curlybracket + // expression is a comprehension array, destructuring assignment or a json value. + + var lookupBlockType = function () { + var pn, pn1; + var i = -1; + var bracketStack = 0; + var ret = {}; + if (_.contains(["[", "{"], state.tokens.curr.value)) + bracketStack += 1; + do { + pn = (i === -1) ? state.tokens.next : peek(i); + pn1 = peek(i + 1); + i = i + 1; + if (_.contains(["[", "{"], pn.value)) { + bracketStack += 1; + } else if (_.contains(["]", "}"], pn.value)) { + bracketStack -= 1; + } + if (pn.identifier && pn.value === "for" && bracketStack === 1) { + ret.isCompArray = true; + ret.notJson = true; + break; + } + if (_.contains(["}", "]"], pn.value) && pn1.value === "=" && bracketStack === 0) { + ret.isDestAssign = true; + ret.notJson = true; + break; + } + if (pn.value === ";") { + ret.isBlock = true; + ret.notJson = true; + } + } while (bracketStack > 0 && pn.id !== "(end)" && i < 15); + return ret; + }; + + // Check whether this function has been reached for a destructuring assign with undeclared values + function destructuringAssignOrJsonValue() { + // lookup for the assignment (esnext only) + // if it has semicolons, it is a block, so go parse it as a block + // or it's not a block, but there are assignments, check for undeclared variables + + var block = lookupBlockType(); + if (block.notJson) { + if (!state.option.inESNext() && block.isDestAssign) { + warning("W104", state.tokens.curr, "destructuring assignment"); + } + statements(); + // otherwise parse json value + } else { + state.option.laxbreak = true; + state.jsonMode = true; + jsonValue(); + } + } + + // array comprehension parsing function + // parses and defines the three states of the list comprehension in order + // to avoid defining global variables, but keeping them to the list comprehension scope + // only. The order of the states are as follows: + // * "use" which will be the returned iterative part of the list comprehension + // * "define" which will define the variables local to the list comprehension + // * "filter" which will help filter out values + + var arrayComprehension = function () { + var CompArray = function () { + this.mode = "use"; + this.variables = []; + }; + var _carrays = []; + var _current; + function declare(v) { + var l = _current.variables.filter(function (elt) { + // if it has, change its undef state + if (elt.value === v) { + elt.undef = false; + return v; + } + }).length; + return l !== 0; + } + function use(v) { + var l = _current.variables.filter(function (elt) { + // and if it has been defined + if (elt.value === v && !elt.undef) { + if (elt.unused === true) { + elt.unused = false; + } + return v; + } + }).length; + // otherwise we warn about it + return (l === 0); + } + return {stack: function () { + _current = new CompArray(); + _carrays.push(_current); + }, + unstack: function () { + _current.variables.filter(function (v) { + if (v.unused) + warning("W098", v.token, v.value); + if (v.undef) + isundef(v.funct, "W117", v.token, v.value); + }); + _carrays.splice(-1, 1); + _current = _carrays[_carrays.length - 1]; + }, + setState: function (s) { + if (_.contains(["use", "define", "generate", "filter"], s)) + _current.mode = s; + }, + check: function (v) { + if (!_current) { + return; + } + // When we are in "use" state of the list comp, we enqueue that var + if (_current && _current.mode === "use") { + if (use(v)) { + _current.variables.push({ + funct: funct, + token: state.tokens.curr, + value: v, + undef: true, + unused: false + }); + } + return true; + // When we are in "define" state of the list comp, + } else if (_current && _current.mode === "define") { + // check if the variable has been used previously + if (!declare(v)) { + _current.variables.push({ + funct: funct, + token: state.tokens.curr, + value: v, + undef: false, + unused: true + }); + } + return true; + // When we are in the "generate" state of the list comp, + } else if (_current && _current.mode === "generate") { + isundef(funct, "W117", state.tokens.curr, v); + return true; + // When we are in "filter" state, + } else if (_current && _current.mode === "filter") { + // we check whether current variable has been declared + if (use(v)) { + // if not we warn about it + isundef(funct, "W117", state.tokens.curr, v); + } + return true; + } + return false; + } + }; + }; + + + // Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = state.tokens.next; + advance("{"); + if (state.tokens.next.id !== "}") { + for (;;) { + if (state.tokens.next.id === "(end)") { + error("E026", state.tokens.next, t.line); + } else if (state.tokens.next.id === "}") { + warning("W094", state.tokens.curr); + break; + } else if (state.tokens.next.id === ",") { + error("E028", state.tokens.next); + } else if (state.tokens.next.id !== "(string)") { + warning("W095", state.tokens.next, state.tokens.next.value); + } + if (o[state.tokens.next.value] === true) { + warning("W075", state.tokens.next, state.tokens.next.value); + } else if ((state.tokens.next.value === "__proto__" && + !state.option.proto) || (state.tokens.next.value === "__iterator__" && + !state.option.iterator)) { + warning("W096", state.tokens.next, state.tokens.next.value); + } else { + o[state.tokens.next.value] = true; + } + advance(); + advance(":"); + jsonValue(); + if (state.tokens.next.id !== ",") { + break; + } + advance(","); + } + } + advance("}"); + } + + function jsonArray() { + var t = state.tokens.next; + advance("["); + if (state.tokens.next.id !== "]") { + for (;;) { + if (state.tokens.next.id === "(end)") { + error("E027", state.tokens.next, t.line); + } else if (state.tokens.next.id === "]") { + warning("W094", state.tokens.curr); + break; + } else if (state.tokens.next.id === ",") { + error("E028", state.tokens.next); + } + jsonValue(); + if (state.tokens.next.id !== ",") { + break; + } + advance(","); + } + } + advance("]"); + } + + switch (state.tokens.next.id) { + case "{": + jsonObject(); + break; + case "[": + jsonArray(); + break; + case "true": + case "false": + case "null": + case "(number)": + case "(string)": + advance(); + break; + case "-": + advance("-"); + if (state.tokens.curr.character !== state.tokens.next.from) { + warning("W011", state.tokens.curr); + } + adjacent(state.tokens.curr, state.tokens.next); + advance("(number)"); + break; + default: + error("E003", state.tokens.next); + } + } + + var blockScope = function () { + var _current = {}; + var _variables = [_current]; + + function _checkBlockLabels() { + for (var t in _current) { + if (_current[t]["(type)"] === "unused") { + if (state.option.unused) { + var tkn = _current[t]["(token)"]; + var line = tkn.line; + var chr = tkn.character; + warningAt("W098", line, chr, t); + } + } + } + } + + return { + stack: function () { + _current = {}; + _variables.push(_current); + }, + + unstack: function () { + _checkBlockLabels(); + _variables.splice(_variables.length - 1, 1); + _current = _.last(_variables); + }, + + getlabel: function (l) { + for (var i = _variables.length - 1 ; i >= 0; --i) { + if (_.has(_variables[i], l)) { + return _variables[i]; + } + } + }, + + current: { + has: function (t) { + return _.has(_current, t); + }, + add: function (t, type, tok) { + _current[t] = { "(type)" : type, + "(token)": tok }; + } + } + }; + }; + + // The actual JSHINT function itself. + var itself = function (s, o, g) { + var i, k, x; + var optionKeys; + var newOptionObj = {}; + var newIgnoredObj = {}; + + state.reset(); + + if (o && o.scope) { + JSHINT.scope = o.scope; + } else { + JSHINT.errors = []; + JSHINT.undefs = []; + JSHINT.internals = []; + JSHINT.blacklist = {}; + JSHINT.scope = "(main)"; + } + + predefined = Object.create(null); + combine(predefined, vars.ecmaIdentifiers); + combine(predefined, vars.reservedVars); + + combine(predefined, g || {}); + + declared = Object.create(null); + exported = Object.create(null); + + function each(obj, cb) { + if (!obj) + return; + + if (!Array.isArray(obj) && typeof obj === "object") + obj = Object.keys(obj); + + obj.forEach(cb); + } + + if (o) { + each(o.predef || null, function (item) { + var slice, prop; + + if (item[0] === "-") { + slice = item.slice(1); + JSHINT.blacklist[slice] = slice; + } else { + prop = Object.getOwnPropertyDescriptor(o.predef, item); + predefined[item] = prop ? prop.value : false; + } + }); + + each(o.exported || null, function (item) { + exported[item] = true; + }); + + delete o.predef; + delete o.exported; + + optionKeys = Object.keys(o); + for (x = 0; x < optionKeys.length; x++) { + if (/^-W\d{3}$/g.test(optionKeys[x])) { + newIgnoredObj[optionKeys[x].slice(1)] = true; + } else { + newOptionObj[optionKeys[x]] = o[optionKeys[x]]; + + if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false) + newOptionObj["(explicitNewcap)"] = true; + + if (optionKeys[x] === "indent") + newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true; + } + } + } + + state.option = newOptionObj; + state.ignored = newIgnoredObj; + + state.option.indent = state.option.indent || 4; + state.option.maxerr = state.option.maxerr || 50; + + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + "(global)": true, + "(name)": "(global)", + "(scope)": scope, + "(breakage)": 0, + "(loopage)": 0, + "(tokens)": {}, + "(metrics)": createMetrics(state.tokens.next), + "(blockscope)": blockScope(), + "(comparray)": arrayComprehension() + }; + functions = [funct]; + urls = []; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + warnings = 0; + unuseds = []; + + if (!isString(s) && !Array.isArray(s)) { + errorAt("E004", 0); + return false; + } + + api = { + get isJSON() { + return state.jsonMode; + }, + + getOption: function (name) { + return state.option[name] || null; + }, + + getCache: function (name) { + return state.cache[name]; + }, + + setCache: function (name, value) { + state.cache[name] = value; + }, + + warn: function (code, data) { + warningAt.apply(null, [ code, data.line, data.char ].concat(data.data)); + }, + + on: function (names, listener) { + names.split(" ").forEach(function (name) { + emitter.on(name, listener); + }.bind(this)); + } + }; + + emitter.removeAllListeners(); + (extraModules || []).forEach(function (func) { + func(api); + }); + + state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"]; + + lex = new Lexer(s); + + lex.on("warning", function (ev) { + warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data)); + }); + + lex.on("error", function (ev) { + errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data)); + }); + + lex.on("fatal", function (ev) { + quit("E041", ev.line, ev.from); + }); + + lex.on("Identifier", function (ev) { + emitter.emit("Identifier", ev); + }); + + lex.on("String", function (ev) { + emitter.emit("String", ev); + }); + + lex.on("Number", function (ev) { + emitter.emit("Number", ev); + }); + + lex.start(); + + // Check options + for (var name in o) { + if (_.has(o, name)) { + checkOption(name, state.tokens.curr); + } + } + + assume(); + + // combine the passed globals after we've assumed all our options + combine(predefined, g || {}); + + //reset values + comma.first = true; + + try { + advance(); + switch (state.tokens.next.id) { + case "{": + case "[": + destructuringAssignOrJsonValue(); + break; + default: + directives(); + + if (state.directive["use strict"]) { + if (!state.option.globalstrict && !(state.option.node || state.option.phantom)) { + warning("W097", state.tokens.prev); + } + } + + statements(); + } + advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined); + funct["(blockscope)"].unstack(); + + var markDefined = function (name, context) { + do { + if (typeof context[name] === "string") { + // JSHINT marks unused variables as 'unused' and + // unused function declaration as 'unction'. This + // code changes such instances back 'var' and + // 'closure' so that the code in JSHINT.data() + // doesn't think they're unused. + + if (context[name] === "unused") + context[name] = "var"; + else if (context[name] === "unction") + context[name] = "closure"; + + return true; + } + + context = context["(context)"]; + } while (context); + + return false; + }; + + var clearImplied = function (name, line) { + if (!implied[name]) + return; + + var newImplied = []; + for (var i = 0; i < implied[name].length; i += 1) { + if (implied[name][i] !== line) + newImplied.push(implied[name][i]); + } + + if (newImplied.length === 0) + delete implied[name]; + else + implied[name] = newImplied; + }; + + var warnUnused = function (name, tkn, type, unused_opt) { + var line = tkn.line; + var chr = tkn.character; + + if (unused_opt === undefined) { + unused_opt = state.option.unused; + } + + if (unused_opt === true) { + unused_opt = "last-param"; + } + + var warnable_types = { + "vars": ["var"], + "last-param": ["var", "param"], + "strict": ["var", "param", "last-param"] + }; + + if (unused_opt) { + if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) { + warningAt("W098", line, chr, name); + } + } + + unuseds.push({ + name: name, + line: line, + character: chr + }); + }; + + var checkUnused = function (func, key) { + var type = func[key]; + var tkn = func["(tokens)"][key]; + + if (key.charAt(0) === "(") + return; + + if (type !== "unused" && type !== "unction") + return; + + // Params are checked separately from other variables. + if (func["(params)"] && func["(params)"].indexOf(key) !== -1) + return; + + // Variable is in global scope and defined as exported. + if (func["(global)"] && _.has(exported, key)) { + return; + } + + warnUnused(key, tkn, "var"); + }; + + // Check queued 'x is not defined' instances to see if they're still undefined. + for (i = 0; i < JSHINT.undefs.length; i += 1) { + k = JSHINT.undefs[i].slice(0); + + if (markDefined(k[2].value, k[0])) { + clearImplied(k[2].value, k[2].line); + } else if (state.option.undef) { + warning.apply(warning, k.slice(1)); + } + } + + functions.forEach(function (func) { + if (func["(unusedOption)"] === false) { + return; + } + + for (var key in func) { + if (_.has(func, key)) { + checkUnused(func, key); + } + } + + if (!func["(params)"]) + return; + + var params = func["(params)"].slice(); + var param = params.pop(); + var type, unused_opt; + + while (param) { + type = func[param]; + unused_opt = func["(unusedOption)"] || state.option.unused; + unused_opt = unused_opt === true ? "last-param" : unused_opt; + + // 'undefined' is a special case for (function (window, undefined) { ... })(); + // patterns. + + if (param === "undefined") + return; + + if (type === "unused" || type === "unction") { + warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]); + } else if (unused_opt === "last-param") { + return; + } + + param = params.pop(); + } + }); + + for (var key in declared) { + if (_.has(declared, key) && !_.has(global, key)) { + warnUnused(key, declared[key], "var"); + } + } + + } catch (err) { + if (err && err.name === "JSHintError") { + var nt = state.tokens.next || {}; + JSHINT.errors.push({ + scope : "(main)", + raw : err.raw, + code : err.code, + reason : err.message, + line : err.line || nt.line, + character : err.character || nt.from + }, null); + } else { + throw err; + } + } + + // Loop over the listed "internals", and check them as well. + + if (JSHINT.scope === "(main)") { + o = o || {}; + + for (i = 0; i < JSHINT.internals.length; i += 1) { + k = JSHINT.internals[i]; + o.scope = k.elem; + itself(k.value, o, g); + } + } + + return JSHINT.errors.length === 0; + }; + + // Modules. + itself.addModule = function (func) { + extraModules.push(func); + }; + + itself.addModule(style.register); + + // Data summary. + itself.data = function () { + var data = { + functions: [], + options: state.option + }; + + var implieds = []; + var members = []; + var fu, f, i, j, n, globals; + + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (state.jsonMode) { + data.json = true; + } + + for (n in implied) { + if (_.has(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + + fu.name = f["(name)"]; + fu.param = f["(params)"]; + fu.line = f["(line)"]; + fu.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; + + fu.metrics = { + complexity: f["(metrics)"].ComplexityCount, + parameters: (f["(params)"] || []).length, + statements: f["(metrics)"].statementCount + }; + + data.functions.push(fu); + } + + if (unuseds.length > 0) { + data.unused = unuseds; + } + + members = []; + for (n in member) { + if (typeof member[n] === "number") { + data.member = member; + break; + } + } + + return data; + }; + + itself.jshint = itself; + + return itself; +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports === "object" && exports) { + exports.JSHINT = JSHINT; +} diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/lex.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/lex.js new file mode 100644 index 000000000..ccdb4cce7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/lex.js @@ -0,0 +1,1694 @@ +/* + * Lexical analysis and token construction. + */ + +"use strict"; + +var _ = require("underscore"); +var events = require("events"); +var reg = require("./reg.js"); +var state = require("./state.js").state; + +// Some of these token types are from JavaScript Parser API +// while others are specific to JSHint parser. +// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + +var Token = { + Identifier: 1, + Punctuator: 2, + NumericLiteral: 3, + StringLiteral: 4, + Comment: 5, + Keyword: 6, + NullLiteral: 7, + BooleanLiteral: 8, + RegExp: 9 +}; + +// This is auto generated from the unicode tables. +// The tables are at: +// http://www.fileformat.info/info/unicode/category/Lu/list.htm +// http://www.fileformat.info/info/unicode/category/Ll/list.htm +// http://www.fileformat.info/info/unicode/category/Lt/list.htm +// http://www.fileformat.info/info/unicode/category/Lm/list.htm +// http://www.fileformat.info/info/unicode/category/Lo/list.htm +// http://www.fileformat.info/info/unicode/category/Nl/list.htm + +var unicodeLetterTable = [ + 170, 170, 181, 181, 186, 186, 192, 214, + 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, + 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, + 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, + 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, + 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, + 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, + 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, + 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361, + 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, + 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, + 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, + 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, + 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, + 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, + 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, + 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, + 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, + 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, + 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, + 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, + 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, + 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, + 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, + 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, + 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, + 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, + 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, + 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, + 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, + 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, + 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, + 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346, + 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696, + 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, + 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, + 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, + 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, + 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, + 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, + 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, + 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, + 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141, + 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, + 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, + 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, + 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, + 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, + 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, + 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, + 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, + 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, + 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621, + 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, + 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, + 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, + 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, + 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, + 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312, + 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124, + 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, + 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, + 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921, + 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042, + 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, + 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, + 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, + 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, + 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, + 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798, + 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032, + 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045, + 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279, + 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, + 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, + 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, + 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, + 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, + 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, + 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, + 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334, + 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511, + 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592, + 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, + 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115, + 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405, + 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687, + 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894, + 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964, + 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, + 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, + 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, + 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, + 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, + 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, + 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, + 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972, + 177984, 177984, 178205, 178205, 194560, 195101 +]; + +var identifierStartTable = []; + +for (var i = 0; i < 128; i++) { + identifierStartTable[i] = + i === 36 || // $ + i >= 65 && i <= 90 || // A-Z + i === 95 || // _ + i >= 97 && i <= 122; // a-z +} + +var identifierPartTable = []; + +for (var i = 0; i < 128; i++) { + identifierPartTable[i] = + identifierStartTable[i] || // $, _, A-Z, a-z + i >= 48 && i <= 57; // 0-9 +} + +// Object that handles postponed lexing verifications that checks the parsed +// environment state. + +function asyncTrigger() { + var _checks = []; + + return { + push: function (fn) { + _checks.push(fn); + }, + + check: function () { + for (var check = 0; check < _checks.length; ++check) { + _checks[check](); + } + + _checks.splice(0, _checks.length); + } + }; +} + +/* + * Lexer for JSHint. + * + * This object does a char-by-char scan of the provided source code + * and produces a sequence of tokens. + * + * var lex = new Lexer("var i = 0;"); + * lex.start(); + * lex.token(); // returns the next token + * + * You have to use the token() method to move the lexer forward + * but you don't have to use its return value to get tokens. In addition + * to token() method returning the next token, the Lexer object also + * emits events. + * + * lex.on("Identifier", function (data) { + * if (data.name.indexOf("_") >= 0) { + * // Produce a warning. + * } + * }); + * + * Note that the token() method returns tokens in a JSLint-compatible + * format while the event emitter uses a slightly modified version of + * Mozilla's JavaScript Parser API. Eventually, we will move away from + * JSLint format. + */ +function Lexer(source) { + var lines = source; + + if (typeof lines === "string") { + lines = lines + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n"); + } + + // If the first line is a shebang (#!), make it a blank and move on. + // Shebangs are used by Node scripts. + + if (lines[0] && lines[0].substr(0, 2) === "#!") { + lines[0] = ""; + } + + this.emitter = new events.EventEmitter(); + this.source = source; + this.setLines(lines); + this.prereg = true; + + this.line = 0; + this.char = 1; + this.from = 1; + this.input = ""; + + for (var i = 0; i < state.option.indent; i += 1) { + state.tab += " "; + } +} + +Lexer.prototype = { + _lines: [], + + getLines: function () { + this._lines = state.lines; + return this._lines; + }, + + setLines: function (val) { + this._lines = val; + state.lines = this._lines; + }, + + /* + * Return the next i character without actually moving the + * char pointer. + */ + peek: function (i) { + return this.input.charAt(i || 0); + }, + + /* + * Move the char pointer forward i times. + */ + skip: function (i) { + i = i || 1; + this.char += i; + this.input = this.input.slice(i); + }, + + /* + * Subscribe to a token event. The API for this method is similar + * Underscore.js i.e. you can subscribe to multiple events with + * one call: + * + * lex.on("Identifier Number", function (data) { + * // ... + * }); + */ + on: function (names, listener) { + names.split(" ").forEach(function (name) { + this.emitter.on(name, listener); + }.bind(this)); + }, + + /* + * Trigger a token event. All arguments will be passed to each + * listener. + */ + trigger: function () { + this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments)); + }, + + /* + * Postpone a token event. the checking condition is set as + * last parameter, and the trigger function is called in a + * stored callback. To be later called using the check() function + * by the parser. This avoids parser's peek() to give the lexer + * a false context. + */ + triggerAsync: function (type, args, checks, fn) { + checks.push(function () { + if (fn()) { + this.trigger(type, args); + } + }.bind(this)); + }, + + /* + * Extract a punctuator out of the next sequence of characters + * or return 'null' if its not possible. + * + * This method's implementation was heavily influenced by the + * scanPunctuator function in the Esprima parser's source code. + */ + scanPunctuator: function () { + var ch1 = this.peek(); + var ch2, ch3, ch4; + + switch (ch1) { + // Most common single-character punctuators + case ".": + if ((/^[0-9]$/).test(this.peek(1))) { + return null; + } + if (this.peek(1) === "." && this.peek(2) === ".") { + return { + type: Token.Punctuator, + value: "..." + }; + } + /* falls through */ + case "(": + case ")": + case ";": + case ",": + case "{": + case "}": + case "[": + case "]": + case ":": + case "~": + case "?": + return { + type: Token.Punctuator, + value: ch1 + }; + + // A pound sign (for Node shebangs) + case "#": + return { + type: Token.Punctuator, + value: ch1 + }; + + // We're at the end of input + case "": + return null; + } + + // Peek more characters + + ch2 = this.peek(1); + ch3 = this.peek(2); + ch4 = this.peek(3); + + // 4-character punctuator: >>>= + + if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") { + return { + type: Token.Punctuator, + value: ">>>=" + }; + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === "=" && ch2 === "=" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "===" + }; + } + + if (ch1 === "!" && ch2 === "=" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "!==" + }; + } + + if (ch1 === ">" && ch2 === ">" && ch3 === ">") { + return { + type: Token.Punctuator, + value: ">>>" + }; + } + + if (ch1 === "<" && ch2 === "<" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "<<=" + }; + } + + if (ch1 === ">" && ch2 === ">" && ch3 === "=") { + return { + type: Token.Punctuator, + value: ">>=" + }; + } + + // Fat arrow punctuator + if (ch1 === "=" && ch2 === ">") { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + + // 2-character punctuators: <= >= == != ++ -- << >> && || + // += -= *= %= &= |= ^= (but not /=, see below) + if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + + if ("<>=!+-*%&|^".indexOf(ch1) >= 0) { + if (ch2 === "=") { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + + return { + type: Token.Punctuator, + value: ch1 + }; + } + + // Special case: /=. We need to make sure that this is an + // operator and not a regular expression. + + if (ch1 === "/") { + if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) { + // /= is not a part of a regular expression, return it as a + // punctuator. + return { + type: Token.Punctuator, + value: "/=" + }; + } + + return { + type: Token.Punctuator, + value: "/" + }; + } + + return null; + }, + + /* + * Extract a comment out of the next sequence of characters and/or + * lines or return 'null' if its not possible. Since comments can + * span across multiple lines this method has to move the char + * pointer. + * + * In addition to normal JavaScript comments (// and /*) this method + * also recognizes JSHint- and JSLint-specific comments such as + * /*jshint, /*jslint, /*globals and so on. + */ + scanComments: function () { + var ch1 = this.peek(); + var ch2 = this.peek(1); + var rest = this.input.substr(2); + var startLine = this.line; + var startChar = this.char; + + // Create a comment token object and make sure it + // has all the data JSHint needs to work with special + // comments. + + function commentToken(label, body, opt) { + var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"]; + var isSpecial = false; + var value = label + body; + var commentType = "plain"; + opt = opt || {}; + + if (opt.isMultiline) { + value += "*/"; + } + + special.forEach(function (str) { + if (isSpecial) { + return; + } + + // Don't recognize any special comments other than jshint for single-line + // comments. This introduced many problems with legit comments. + if (label === "//" && str !== "jshint") { + return; + } + + if (body.substr(0, str.length) === str) { + isSpecial = true; + label = label + str; + body = body.substr(str.length); + } + + if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) { + isSpecial = true; + label = label + " " + str; + body = body.substr(str.length + 1); + } + + if (!isSpecial) { + return; + } + + switch (str) { + case "member": + commentType = "members"; + break; + case "global": + commentType = "globals"; + break; + default: + commentType = str; + } + }); + + return { + type: Token.Comment, + commentType: commentType, + value: value, + body: body, + isSpecial: isSpecial, + isMultiline: opt.isMultiline || false, + isMalformed: opt.isMalformed || false + }; + } + + // End of unbegun comment. Raise an error and skip that input. + if (ch1 === "*" && ch2 === "/") { + this.trigger("error", { + code: "E018", + line: startLine, + character: startChar + }); + + this.skip(2); + return null; + } + + // Comments must start either with // or /* + if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) { + return null; + } + + // One-line comment + if (ch2 === "/") { + this.skip(this.input.length); // Skip to the EOL. + return commentToken("//", rest); + } + + var body = ""; + + /* Multi-line comment */ + if (ch2 === "*") { + this.skip(2); + + while (this.peek() !== "*" || this.peek(1) !== "/") { + if (this.peek() === "") { // End of Line + body += "\n"; + + // If we hit EOF and our comment is still unclosed, + // trigger an error and end the comment implicitly. + if (!this.nextLine()) { + this.trigger("error", { + code: "E017", + line: startLine, + character: startChar + }); + + return commentToken("/*", body, { + isMultiline: true, + isMalformed: true + }); + } + } else { + body += this.peek(); + this.skip(); + } + } + + this.skip(2); + return commentToken("/*", body, { isMultiline: true }); + } + }, + + /* + * Extract a keyword out of the next sequence of characters or + * return 'null' if its not possible. + */ + scanKeyword: function () { + var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input); + var keywords = [ + "if", "in", "do", "var", "for", "new", + "try", "let", "this", "else", "case", + "void", "with", "enum", "while", "break", + "catch", "throw", "const", "yield", "class", + "super", "return", "typeof", "delete", + "switch", "export", "import", "default", + "finally", "extends", "function", "continue", + "debugger", "instanceof" + ]; + + if (result && keywords.indexOf(result[0]) >= 0) { + return { + type: Token.Keyword, + value: result[0] + }; + } + + return null; + }, + + /* + * Extract a JavaScript identifier out of the next sequence of + * characters or return 'null' if its not possible. In addition, + * to Identifier this method can also produce BooleanLiteral + * (true/false) and NullLiteral (null). + */ + scanIdentifier: function () { + var id = ""; + var index = 0; + var type, char; + + // Detects any character in the Unicode categories "Uppercase + // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter + // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or + // "Letter number (Nl)". + // + // Both approach and unicodeLetterTable were borrowed from + // Google's Traceur. + + function isUnicodeLetter(code) { + for (var i = 0; i < unicodeLetterTable.length;) { + if (code < unicodeLetterTable[i++]) { + return false; + } + + if (code <= unicodeLetterTable[i++]) { + return true; + } + } + + return false; + } + + function isHexDigit(str) { + return (/^[0-9a-fA-F]$/).test(str); + } + + var readUnicodeEscapeSequence = function () { + /*jshint validthis:true */ + index += 1; + + if (this.peek(index) !== "u") { + return null; + } + + var ch1 = this.peek(index + 1); + var ch2 = this.peek(index + 2); + var ch3 = this.peek(index + 3); + var ch4 = this.peek(index + 4); + var code; + + if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) { + code = parseInt(ch1 + ch2 + ch3 + ch4, 16); + + if (isUnicodeLetter(code)) { + index += 5; + return "\\u" + ch1 + ch2 + ch3 + ch4; + } + + return null; + } + + return null; + }.bind(this); + + var getIdentifierStart = function () { + /*jshint validthis:true */ + var chr = this.peek(index); + var code = chr.charCodeAt(0); + + if (code === 92) { + return readUnicodeEscapeSequence(); + } + + if (code < 128) { + if (identifierStartTable[code]) { + index += 1; + return chr; + } + + return null; + } + + if (isUnicodeLetter(code)) { + index += 1; + return chr; + } + + return null; + }.bind(this); + + var getIdentifierPart = function () { + /*jshint validthis:true */ + var chr = this.peek(index); + var code = chr.charCodeAt(0); + + if (code === 92) { + return readUnicodeEscapeSequence(); + } + + if (code < 128) { + if (identifierPartTable[code]) { + index += 1; + return chr; + } + + return null; + } + + if (isUnicodeLetter(code)) { + index += 1; + return chr; + } + + return null; + }.bind(this); + + char = getIdentifierStart(); + if (char === null) { + return null; + } + + id = char; + for (;;) { + char = getIdentifierPart(); + + if (char === null) { + break; + } + + id += char; + } + + switch (id) { + case "true": + case "false": + type = Token.BooleanLiteral; + break; + case "null": + type = Token.NullLiteral; + break; + default: + type = Token.Identifier; + } + + return { + type: type, + value: id + }; + }, + + /* + * Extract a numeric literal out of the next sequence of + * characters or return 'null' if its not possible. This method + * supports all numeric literals described in section 7.8.3 + * of the EcmaScript 5 specification. + * + * This method's implementation was heavily influenced by the + * scanNumericLiteral function in the Esprima parser's source code. + */ + scanNumericLiteral: function () { + var index = 0; + var value = ""; + var length = this.input.length; + var char = this.peek(index); + var bad; + + function isDecimalDigit(str) { + return (/^[0-9]$/).test(str); + } + + function isOctalDigit(str) { + return (/^[0-7]$/).test(str); + } + + function isHexDigit(str) { + return (/^[0-9a-fA-F]$/).test(str); + } + + function isIdentifierStart(ch) { + return (ch === "$") || (ch === "_") || (ch === "\\") || + (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z"); + } + + // Numbers must start either with a decimal digit or a point. + + if (char !== "." && !isDecimalDigit(char)) { + return null; + } + + if (char !== ".") { + value = this.peek(index); + index += 1; + char = this.peek(index); + + if (value === "0") { + // Base-16 numbers. + if (char === "x" || char === "X") { + index += 1; + value += char; + + while (index < length) { + char = this.peek(index); + if (!isHexDigit(char)) { + break; + } + value += char; + index += 1; + } + + if (value.length <= 2) { // 0x + return { + type: Token.NumericLiteral, + value: value, + isMalformed: true + }; + } + + if (index < length) { + char = this.peek(index); + if (isIdentifierStart(char)) { + return null; + } + } + + return { + type: Token.NumericLiteral, + value: value, + base: 16, + isMalformed: false + }; + } + + // Base-8 numbers. + if (isOctalDigit(char)) { + index += 1; + value += char; + bad = false; + + while (index < length) { + char = this.peek(index); + + // Numbers like '019' (note the 9) are not valid octals + // but we still parse them and mark as malformed. + + if (isDecimalDigit(char)) { + bad = true; + } else if (!isOctalDigit(char)) { + break; + } + value += char; + index += 1; + } + + if (index < length) { + char = this.peek(index); + if (isIdentifierStart(char)) { + return null; + } + } + + return { + type: Token.NumericLiteral, + value: value, + base: 8, + isMalformed: false + }; + } + + // Decimal numbers that start with '0' such as '09' are illegal + // but we still parse them and return as malformed. + + if (isDecimalDigit(char)) { + index += 1; + value += char; + } + } + + while (index < length) { + char = this.peek(index); + if (!isDecimalDigit(char)) { + break; + } + value += char; + index += 1; + } + } + + // Decimal digits. + + if (char === ".") { + value += char; + index += 1; + + while (index < length) { + char = this.peek(index); + if (!isDecimalDigit(char)) { + break; + } + value += char; + index += 1; + } + } + + // Exponent part. + + if (char === "e" || char === "E") { + value += char; + index += 1; + char = this.peek(index); + + if (char === "+" || char === "-") { + value += this.peek(index); + index += 1; + } + + char = this.peek(index); + if (isDecimalDigit(char)) { + value += char; + index += 1; + + while (index < length) { + char = this.peek(index); + if (!isDecimalDigit(char)) { + break; + } + value += char; + index += 1; + } + } else { + return null; + } + } + + if (index < length) { + char = this.peek(index); + if (isIdentifierStart(char)) { + return null; + } + } + + return { + type: Token.NumericLiteral, + value: value, + base: 10, + isMalformed: !isFinite(value) + }; + }, + + /* + * Extract a string out of the next sequence of characters and/or + * lines or return 'null' if its not possible. Since strings can + * span across multiple lines this method has to move the char + * pointer. + * + * This method recognizes pseudo-multiline JavaScript strings: + * + * var str = "hello\ + * world"; + */ + scanStringLiteral: function (checks) { + /*jshint loopfunc:true */ + var quote = this.peek(); + + // String must start with a quote. + if (quote !== "\"" && quote !== "'") { + return null; + } + + // In JSON strings must always use double quotes. + this.triggerAsync("warning", { + code: "W108", + line: this.line, + character: this.char // +1? + }, checks, function () { return state.jsonMode && quote !== "\""; }); + + var value = ""; + var startLine = this.line; + var startChar = this.char; + var allowNewLine = false; + + this.skip(); + + while (this.peek() !== quote) { + while (this.peek() === "") { // End Of Line + + // If an EOL is not preceded by a backslash, show a warning + // and proceed like it was a legit multi-line string where + // author simply forgot to escape the newline symbol. + // + // Another approach is to implicitly close a string on EOL + // but it generates too many false positives. + + if (!allowNewLine) { + this.trigger("warning", { + code: "W112", + line: this.line, + character: this.char + }); + } else { + allowNewLine = false; + + // Otherwise show a warning if multistr option was not set. + // For JSON, show warning no matter what. + + this.triggerAsync("warning", { + code: "W043", + line: this.line, + character: this.char + }, checks, function () { return !state.option.multistr; }); + + this.triggerAsync("warning", { + code: "W042", + line: this.line, + character: this.char + }, checks, function () { return state.jsonMode && state.option.multistr; }); + } + + // If we get an EOF inside of an unclosed string, show an + // error and implicitly close it at the EOF point. + + if (!this.nextLine()) { + this.trigger("error", { + code: "E029", + line: startLine, + character: startChar + }); + + return { + type: Token.StringLiteral, + value: value, + isUnclosed: true, + quote: quote + }; + } + } + + allowNewLine = false; + var char = this.peek(); + var jump = 1; // A length of a jump, after we're done + // parsing this character. + + if (char < " ") { + // Warn about a control character in a string. + this.trigger("warning", { + code: "W113", + line: this.line, + character: this.char, + data: [ "" ] + }); + } + + // Special treatment for some escaped characters. + + if (char === "\\") { + this.skip(); + char = this.peek(); + + switch (char) { + case "'": + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\'" ] + }, checks, function () {return state.jsonMode; }); + break; + case "b": + char = "\b"; + break; + case "f": + char = "\f"; + break; + case "n": + char = "\n"; + break; + case "r": + char = "\r"; + break; + case "t": + char = "\t"; + break; + case "0": + char = "\0"; + + // Octal literals fail in strict mode. + // Check if the number is between 00 and 07. + var n = parseInt(this.peek(1), 10); + this.triggerAsync("warning", { + code: "W115", + line: this.line, + character: this.char + }, checks, + function () { return n >= 0 && n <= 7 && state.directive["use strict"]; }); + break; + case "u": + char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16)); + jump = 5; + break; + case "v": + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\v" ] + }, checks, function () { return state.jsonMode; }); + + char = "\v"; + break; + case "x": + var x = parseInt(this.input.substr(1, 2), 16); + + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\x-" ] + }, checks, function () { return state.jsonMode; }); + + char = String.fromCharCode(x); + jump = 3; + break; + case "\\": + case "\"": + case "/": + break; + case "": + allowNewLine = true; + char = ""; + break; + case "!": + if (value.slice(value.length - 2) === "<") { + break; + } + + /*falls through */ + default: + // Weird escaping. + this.trigger("warning", { + code: "W044", + line: this.line, + character: this.char + }); + } + } + + value += char; + this.skip(jump); + } + + this.skip(); + return { + type: Token.StringLiteral, + value: value, + isUnclosed: false, + quote: quote + }; + }, + + /* + * Extract a regular expression out of the next sequence of + * characters and/or lines or return 'null' if its not possible. + * + * This method is platform dependent: it accepts almost any + * regular expression values but then tries to compile and run + * them using system's RegExp object. This means that there are + * rare edge cases where one JavaScript engine complains about + * your regular expression while others don't. + */ + scanRegExp: function () { + var index = 0; + var length = this.input.length; + var char = this.peek(); + var value = char; + var body = ""; + var flags = []; + var malformed = false; + var isCharSet = false; + var terminated; + + var scanUnexpectedChars = function () { + // Unexpected control character + if (char < " ") { + malformed = true; + this.trigger("warning", { + code: "W048", + line: this.line, + character: this.char + }); + } + + // Unexpected escaped character + if (char === "<") { + malformed = true; + this.trigger("warning", { + code: "W049", + line: this.line, + character: this.char, + data: [ char ] + }); + } + }.bind(this); + + // Regular expressions must start with '/' + if (!this.prereg || char !== "/") { + return null; + } + + index += 1; + terminated = false; + + // Try to get everything in between slashes. A couple of + // cases aside (see scanUnexpectedChars) we don't really + // care whether the resulting expression is valid or not. + // We will check that later using the RegExp object. + + while (index < length) { + char = this.peek(index); + value += char; + body += char; + + if (isCharSet) { + if (char === "]") { + if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") { + isCharSet = false; + } + } + + if (char === "\\") { + index += 1; + char = this.peek(index); + body += char; + value += char; + + scanUnexpectedChars(); + } + + index += 1; + continue; + } + + if (char === "\\") { + index += 1; + char = this.peek(index); + body += char; + value += char; + + scanUnexpectedChars(); + + if (char === "/") { + index += 1; + continue; + } + + if (char === "[") { + index += 1; + continue; + } + } + + if (char === "[") { + isCharSet = true; + index += 1; + continue; + } + + if (char === "/") { + body = body.substr(0, body.length - 1); + terminated = true; + index += 1; + break; + } + + index += 1; + } + + // A regular expression that was never closed is an + // error from which we cannot recover. + + if (!terminated) { + this.trigger("error", { + code: "E015", + line: this.line, + character: this.from + }); + + return void this.trigger("fatal", { + line: this.line, + from: this.from + }); + } + + // Parse flags (if any). + + while (index < length) { + char = this.peek(index); + if (!/[gim]/.test(char)) { + break; + } + flags.push(char); + value += char; + index += 1; + } + + // Check regular expression for correctness. + + try { + new RegExp(body, flags.join("")); + } catch (err) { + malformed = true; + this.trigger("error", { + code: "E016", + line: this.line, + character: this.char, + data: [ err.message ] // Platform dependent! + }); + } + + return { + type: Token.RegExp, + value: value, + flags: flags, + isMalformed: malformed + }; + }, + + /* + * Scan for any occurence of mixed tabs and spaces. If smarttabs option + * is on, ignore tabs followed by spaces. + * + * Tabs followed by one space followed by a block comment are allowed. + */ + scanMixedSpacesAndTabs: function () { + var at, match; + + if (state.option.smarttabs) { + // Negative look-behind for "//" + match = this.input.match(/(\/\/|^\s?\*)? \t/); + at = match && !match[1] ? 0 : -1; + } else { + at = this.input.search(/ \t|\t [^\*]/); + } + + return at; + }, + + /* + * Scan for characters that get silently deleted by one or more browsers. + */ + scanUnsafeChars: function () { + return this.input.search(reg.unsafeChars); + }, + + /* + * Produce the next raw token or return 'null' if no tokens can be matched. + * This method skips over all space characters. + */ + next: function (checks) { + this.from = this.char; + + // Move to the next non-space character. + var start; + if (/\s/.test(this.peek())) { + start = this.char; + + while (/\s/.test(this.peek())) { + this.from += 1; + this.skip(); + } + + if (this.peek() === "") { // EOL + if (!/^\s*$/.test(this.getLines()[this.line - 1]) && state.option.trailing) { + this.trigger("warning", { code: "W102", line: this.line, character: start }); + } + } + } + + // Methods that work with multi-line structures and move the + // character pointer. + + var match = this.scanComments() || + this.scanStringLiteral(checks); + + if (match) { + return match; + } + + // Methods that don't move the character pointer. + + match = + this.scanRegExp() || + this.scanPunctuator() || + this.scanKeyword() || + this.scanIdentifier() || + this.scanNumericLiteral(); + + if (match) { + this.skip(match.value.length); + return match; + } + + // No token could be matched, give up. + + return null; + }, + + /* + * Switch to the next line and reset all char pointers. Once + * switched, this method also checks for mixed spaces and tabs + * and other minor warnings. + */ + nextLine: function () { + var char; + + if (this.line >= this.getLines().length) { + return false; + } + + this.input = this.getLines()[this.line]; + this.line += 1; + this.char = 1; + this.from = 1; + + char = this.scanMixedSpacesAndTabs(); + if (char >= 0) { + this.trigger("warning", { code: "W099", line: this.line, character: char + 1 }); + } + + this.input = this.input.replace(/\t/g, state.tab); + char = this.scanUnsafeChars(); + + if (char >= 0) { + this.trigger("warning", { code: "W100", line: this.line, character: char }); + } + + // If there is a limit on line length, warn when lines get too + // long. + + if (state.option.maxlen && state.option.maxlen < this.input.length) { + this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); + } + + return true; + }, + + /* + * This is simply a synonym for nextLine() method with a friendlier + * public name. + */ + start: function () { + this.nextLine(); + }, + + /* + * Produce the next token. This function is called by advance() to get + * the next token. It retuns a token in a JSLint-compatible format. + */ + token: function () { + /*jshint loopfunc:true */ + var checks = asyncTrigger(); + var token; + + + function isReserved(token, isProperty) { + if (!token.reserved) { + return false; + } + var meta = token.meta; + + if (meta && meta.isFutureReservedWord && state.option.inES5()) { + // ES3 FutureReservedWord in an ES5 environment. + if (!meta.es5) { + return false; + } + + // Some ES5 FutureReservedWord identifiers are active only + // within a strict mode environment. + if (meta.strictOnly) { + if (!state.option.strict && !state.directive["use strict"]) { + return false; + } + } + + if (isProperty) { + return false; + } + } + + return true; + } + + // Produce a token object. + var create = function (type, value, isProperty) { + /*jshint validthis:true */ + var obj; + + if (type !== "(endline)" && type !== "(end)") { + this.prereg = false; + } + + if (type === "(punctuator)") { + switch (value) { + case ".": + case ")": + case "~": + case "#": + case "]": + this.prereg = false; + break; + default: + this.prereg = true; + } + + obj = Object.create(state.syntax[value] || state.syntax["(error)"]); + } + + if (type === "(identifier)") { + if (value === "return" || value === "case" || value === "typeof") { + this.prereg = true; + } + + if (_.has(state.syntax, value)) { + obj = Object.create(state.syntax[value] || state.syntax["(error)"]); + + // If this can't be a reserved keyword, reset the object. + if (!isReserved(obj, isProperty && type === "(identifier)")) { + obj = null; + } + } + } + + if (!obj) { + obj = Object.create(state.syntax[type]); + } + + obj.identifier = (type === "(identifier)"); + obj.type = obj.type || type; + obj.value = value; + obj.line = this.line; + obj.character = this.char; + obj.from = this.from; + + if (isProperty && obj.identifier) { + obj.isProperty = isProperty; + } + + obj.check = checks.check; + + return obj; + }.bind(this); + + for (;;) { + if (!this.input.length) { + return create(this.nextLine() ? "(endline)" : "(end)", ""); + } + + token = this.next(checks); + + if (!token) { + if (this.input.length) { + // Unexpected character. + this.trigger("error", { + code: "E024", + line: this.line, + character: this.char, + data: [ this.peek() ] + }); + + this.input = ""; + } + + continue; + } + + switch (token.type) { + case Token.StringLiteral: + this.triggerAsync("String", { + line: this.line, + char: this.char, + from: this.from, + value: token.value, + quote: token.quote + }, checks, function () { return true; }); + + return create("(string)", token.value); + case Token.Identifier: + this.trigger("Identifier", { + line: this.line, + char: this.char, + from: this.form, + name: token.value, + isProperty: state.tokens.curr.id === "." + }); + + /* falls through */ + case Token.Keyword: + case Token.NullLiteral: + case Token.BooleanLiteral: + return create("(identifier)", token.value, state.tokens.curr.id === "."); + + case Token.NumericLiteral: + if (token.isMalformed) { + this.trigger("warning", { + code: "W045", + line: this.line, + character: this.char, + data: [ token.value ] + }); + } + + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "0x-" ] + }, checks, function () { return token.base === 16 && state.jsonMode; }); + + this.triggerAsync("warning", { + code: "W115", + line: this.line, + character: this.char + }, checks, function () { + return state.directive["use strict"] && token.base === 8; + }); + + this.trigger("Number", { + line: this.line, + char: this.char, + from: this.from, + value: token.value, + base: token.base, + isMalformed: token.malformed + }); + + return create("(number)", token.value); + + case Token.RegExp: + return create("(regexp)", token.value); + + case Token.Comment: + state.tokens.curr.comment = true; + + if (token.isSpecial) { + return { + id: '(comment)', + value: token.value, + body: token.body, + type: token.commentType, + isSpecial: token.isSpecial, + line: this.line, + character: this.char, + from: this.from + }; + } + + break; + + case "": + break; + + default: + return create("(punctuator)", token.value); + } + } + } +}; + +exports.Lexer = Lexer; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/messages.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/messages.js new file mode 100644 index 000000000..241ce1666 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/messages.js @@ -0,0 +1,218 @@ +"use strict"; + +var _ = require("underscore"); + +var errors = { + // JSHint options + E001: "Bad option: '{a}'.", + E002: "Bad option value.", + + // JSHint input + E003: "Expected a JSON value.", + E004: "Input is neither a string nor an array of strings.", + E005: "Input is empty.", + E006: "Unexpected early end of program.", + + // Strict mode + E007: "Missing \"use strict\" statement.", + E008: "Strict violation.", + E009: "Option 'validthis' can't be used in a global scope.", + E010: "'with' is not allowed in strict mode.", + + // Constants + E011: "const '{a}' has already been declared.", + E012: "const '{a}' is initialized to 'undefined'.", + E013: "Attempting to override '{a}' which is a constant.", + + // Regular expressions + E014: "A regular expression literal can be confused with '/='.", + E015: "Unclosed regular expression.", + E016: "Invalid regular expression.", + + // Tokens + E017: "Unclosed comment.", + E018: "Unbegun comment.", + E019: "Unmatched '{a}'.", + E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + E021: "Expected '{a}' and instead saw '{b}'.", + E022: "Line breaking error '{a}'.", + E023: "Missing '{a}'.", + E024: "Unexpected '{a}'.", + E025: "Missing ':' on a case clause.", + E026: "Missing '}' to match '{' from line {a}.", + E027: "Missing ']' to match '[' form line {a}.", + E028: "Illegal comma.", + E029: "Unclosed string.", + + // Everything else + E030: "Expected an identifier and instead saw '{a}'.", + E031: "Bad assignment.", // FIXME: Rephrase + E032: "Expected a small integer or 'false' and instead saw '{a}'.", + E033: "Expected an operator and instead saw '{a}'.", + E034: "get/set are ES5 features.", + E035: "Missing property name.", + E036: "Expected to see a statement and instead saw a block.", + E037: null, // Vacant + E038: null, // Vacant + E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.", + E040: "Each value should have its own case label.", + E041: "Unrecoverable syntax error.", + E042: "Stopping.", + E043: "Too many errors.", + E044: "'{a}' is already defined and can't be redefined.", + E045: "Invalid for each loop.", + E046: "A yield statement shall be within a generator function (with syntax: `function*`)", + E047: "A generator function shall contain a yield statement.", + E048: "Let declaration not directly within block.", + E049: "A {a} cannot be named '{b}'.", + E050: "Mozilla requires the yield expression to be parenthesized here.", + E051: "Regular parameters cannot come after default parameters." +}; + +var warnings = { + W001: "'hasOwnProperty' is a really bad name.", + W002: "Value of '{a}' may be overwritten in IE 8 and earlier.", + W003: "'{a}' was used before it was defined.", + W004: "'{a}' is already defined.", + W005: "A dot following a number can be confused with a decimal point.", + W006: "Confusing minuses.", + W007: "Confusing pluses.", + W008: "A leading decimal point can be confused with a dot: '{a}'.", + W009: "The array literal notation [] is preferrable.", + W010: "The object literal notation {} is preferrable.", + W011: "Unexpected space after '{a}'.", + W012: "Unexpected space before '{a}'.", + W013: "Missing space after '{a}'.", + W014: "Bad line breaking before '{a}'.", + W015: "Expected '{a}' to have an indentation at {b} instead at {c}.", + W016: "Unexpected use of '{a}'.", + W017: "Bad operand.", + W018: "Confusing use of '{a}'.", + W019: "Use the isNaN function to compare with NaN.", + W020: "Read only.", + W021: "'{a}' is a function.", + W022: "Do not assign to the exception parameter.", + W023: "Expected an identifier in an assignment and instead saw a function invocation.", + W024: "Expected an identifier and instead saw '{a}' (a reserved word).", + W025: "Missing name in function declaration.", + W026: "Inner functions should be listed at the top of the outer function.", + W027: "Unreachable '{a}' after '{b}'.", + W028: "Label '{a}' on {b} statement.", + W030: "Expected an assignment or function call and instead saw an expression.", + W031: "Do not use 'new' for side effects.", + W032: "Unnecessary semicolon.", + W033: "Missing semicolon.", + W034: "Unnecessary directive \"{a}\".", + W035: "Empty block.", + W036: "Unexpected /*member '{a}'.", + W037: "'{a}' is a statement label.", + W038: "'{a}' used out of scope.", + W039: "'{a}' is not allowed.", + W040: "Possible strict violation.", + W041: "Use '{a}' to compare with '{b}'.", + W042: "Avoid EOL escaping.", + W043: "Bad escaping of EOL. Use option multistr if needed.", + W044: "Bad or unnecessary escaping.", + W045: "Bad number '{a}'.", + W046: "Don't use extra leading zeros '{a}'.", + W047: "A trailing decimal point can be confused with a dot: '{a}'.", + W048: "Unexpected control character in regular expression.", + W049: "Unexpected escaped character '{a}' in regular expression.", + W050: "JavaScript URL.", + W051: "Variables should not be deleted.", + W052: "Unexpected '{a}'.", + W053: "Do not use {a} as a constructor.", + W054: "The Function constructor is a form of eval.", + W055: "A constructor name should start with an uppercase letter.", + W056: "Bad constructor.", + W057: "Weird construction. Is 'new' unnecessary?", + W058: "Missing '()' invoking a constructor.", + W059: "Avoid arguments.{a}.", + W060: "document.write can be a form of eval.", + W061: "eval can be harmful.", + W062: "Wrap an immediate function invocation in parens " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself.", + W063: "Math is not a function.", + W064: "Missing 'new' prefix when invoking a constructor.", + W065: "Missing radix parameter.", + W066: "Implied eval. Consider passing a function instead of a string.", + W067: "Bad invocation.", + W068: "Wrapping non-IIFE function literals in parens is unnecessary.", + W069: "['{a}'] is better written in dot notation.", + W070: "Extra comma. (it breaks older versions of IE)", + W071: "This function has too many statements. ({a})", + W072: "This function has too many parameters. ({a})", + W073: "Blocks are nested too deeply. ({a})", + W074: "This function's cyclomatic complexity is too high. ({a})", + W075: "Duplicate key '{a}'.", + W076: "Unexpected parameter '{a}' in get {b} function.", + W077: "Expected a single parameter in set {a} function.", + W078: "Setter is defined without getter.", + W079: "Redefinition of '{a}'.", + W080: "It's not necessary to initialize '{a}' to 'undefined'.", + W081: "Too many var statements.", + W082: "Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", + W083: "Don't make functions within a loop.", + W084: "Expected a conditional expression and instead saw an assignment.", + W085: "Don't use 'with'.", + W086: "Expected a 'break' statement before '{a}'.", + W087: "Forgotten 'debugger' statement?", + W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.", + W089: "The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", + W090: "'{a}' is not a statement label.", + W091: "'{a}' is out of scope.", + W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.", + W093: "Did you mean to return a conditional instead of an assignment?", + W094: "Unexpected comma.", + W095: "Expected a string and instead saw {a}.", + W096: "The '{a}' key may produce unexpected results.", + W097: "Use the function form of \"use strict\".", + W098: "'{a}' is defined but never used.", + W099: "Mixed spaces and tabs.", + W100: "This character may get silently deleted by one or more browsers.", + W101: "Line is too long.", + W102: "Trailing whitespace.", + W103: "The '{a}' property is deprecated.", + W104: "'{a}' is only available in JavaScript 1.7.", + W105: "Unexpected {a} in '{b}'.", + W106: "Identifier '{a}' is not in camel case.", + W107: "Script URL.", + W108: "Strings must use doublequote.", + W109: "Strings must use singlequote.", + W110: "Mixed double and single quotes.", + W112: "Unclosed string.", + W113: "Control character in string: {a}.", + W114: "Avoid {a}.", + W115: "Octal literals are not allowed in strict mode.", + W116: "Expected '{a}' and instead saw '{b}'.", + W117: "'{a}' is not defined.", + W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).", + W119: "'{a}' is only available in ES6 (use esnext option).", + W120: "You might be leaking a variable ({a}) here." +}; + +var info = { + I001: "Comma warnings can be turned off with 'laxcomma'.", + I002: "Reserved words as properties can be used under the 'es5' option.", + I003: "ES5 option is now set per default" +}; + +exports.errors = {}; +exports.warnings = {}; +exports.info = {}; + +_.each(errors, function (desc, code) { + exports.errors[code] = { code: code, desc: desc }; +}); + +_.each(warnings, function (desc, code) { + exports.warnings[code] = { code: code, desc: desc }; +}); + +_.each(info, function (desc, code) { + exports.info[code] = { code: code, desc: desc }; +}); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/platforms/rhino.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/platforms/rhino.js new file mode 100644 index 000000000..cc4116a7b --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/platforms/rhino.js @@ -0,0 +1,113 @@ +/*jshint boss: true, rhino: true, unused: true, undef: true, white: true, quotmark: double */ +/*global JSHINT */ + +(function (args) { + "use strict"; + + var filenames = []; + var flags = {}; + var optstr; // arg1=val1,arg2=val2,... + var predef; // global1=true,global2,global3,... + var opts = {}; + var globals = {}; + var retval = 0; + + args.forEach(function (arg) { + if (arg.indexOf("--") === 0) { + // Configuration Flags might be boolean or will be split into name and value + if (arg.indexOf("=") > -1) { + var o = arg.split("="); + flags[o[0].slice(2)] = o[1]; + } else { + flags[arg.slice(2)] = true; + } + + return; + } else if (arg.indexOf("=") > -1) { + // usual rhino configuration, like "boss=true,browser=true" + if (!optstr) { + // First time it's the options. + optstr = arg; + } else { + predef = arg; + } + + return; + } + + if (optstr) { + predef = arg; + return; + } + + filenames.push(arg); + }); + + if (filenames.length === 0) { + print("Usage: jshint.js file.js"); + quit(1); + } + + // If a config flag has been provided, try and load that + if ("config" in flags) { + var cfgFileContent; + try { + cfgFileContent = readFile(flags.config); + } catch (e) { + print("Could not read config file " + flags.config); + quit(1); + } + + opts = JSON.parse(cfgFileContent); + } + + if (optstr) { + optstr.split(",").forEach(function (arg) { + var o = arg.split("="); + if (o[0] === "indent") { + opts[o[0]] = parseInt(o[1], 10); + } else { + opts[o[0]] = (function (ov) { + switch (ov) { + case "true": + return true; + case "false": + return false; + default: + return ov; + } + }(o[1])); + } + }); + } + + globals = opts.globals || {}; + delete(opts.globals); + + if (predef) { + predef.split(",").forEach(function (arg) { + var global = arg.split("="); + globals[global[0]] = global[1] === "true" ? true : false; + }); + } + + filenames.forEach(function (name) { + var input = readFile(name); + + if (!input) { + print("jshint: Couldn't open file " + name); + quit(1); + } + + if (!JSHINT(input, opts, globals)) { + for (var i = 0, err; err = JSHINT.errors[i]; i += 1) { + print(err.reason + " (" + name + ":" + err.line + ":" + err.character + ")"); + print("> " + (err.evidence || "").replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); + print(""); + } + retval = 2; + } + }); + + quit(retval); +}(arguments)); diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reg.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reg.js new file mode 100644 index 000000000..5a54a3176 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reg.js @@ -0,0 +1,34 @@ +/* + * Regular expressions. Some of these are stupidly long. + */ + +/*jshint maxlen:1000 */ + +"use string"; + +// Unsafe comment or string (ax) +exports.unsafeString = + /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + +// Unsafe characters that are silently deleted by one or more browsers (cx) +exports.unsafeChars = + /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + +// Characters in strings that need escaping (nx and nxg) +exports.needEsc = + /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + +exports.needEscGlobal = + /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + +// Star slash (lx) +exports.starSlash = /\*\//; + +// Identifier (ix) +exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + +// JavaScript URL (jx) +exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + +// Catches /* falls through */ comments (ft) +exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/checkstyle.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/checkstyle.js new file mode 100644 index 000000000..5306d1cc3 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/checkstyle.js @@ -0,0 +1,115 @@ +// Author: Boy Baukema +// http://github.com/relaxnow +module.exports = +{ + reporter: function (results, data, opts) + { + "use strict"; + + var files = {}, + out = [], + pairs = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">" + }, + file, fileName, i, issue, globals, unuseds, errorMessage; + + opts = opts || {}; + + function encode(s) { + for (var r in pairs) { + if (typeof(s) !== "undefined") { + s = s.replace(new RegExp(r, "g"), pairs[r]); + } + } + return s || ""; + } + + results.forEach(function (result) { + // Register the file + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + + // Create the error message + errorMessage = result.error.reason; + if (opts.verbose) { + errorMessage += ' (' + result.error.code + ')'; + } + + // Add the error + files[result.file].push({ + severity: 'error', + line: result.error.line, + column: result.error.character, + message: errorMessage, + source: 'jshint.' + result.error.code + }); + }); + + data.forEach(function (result) { + file = data.file; + globals = result.implieds; + unuseds = result.unused; + + // Register the file + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + + if (globals) { + globals.forEach(function (global) { + files[result.file].push({ + severity: 'warning', + line: global.line, + column: 0, + message: "Implied global '" + global.name + "'", + source: 'jshint.implied-globals' + }); + }); + } + if (unuseds) { + unuseds.forEach(function (unused) { + files[result.file].push({ + severity: 'warning', + line: unused.line, + column: 0, + message: "Unused variable: '" + unused.name + "'", + source: 'jshint.implied-unuseds' + }); + }); + } + }); + + out.push(""); + out.push(""); + + for (fileName in files) { + if (files.hasOwnProperty(fileName)) { + out.push("\t"); + for (i = 0; i < files[fileName].length; i++) { + issue = files[fileName][i]; + out.push( + "\t\t" + ); + } + out.push("\t"); + } + } + + out.push(""); + + process.stdout.write(out.join("\n") + "\n"); + } +}; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/default.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/default.js new file mode 100644 index 000000000..2a432f18f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/default.js @@ -0,0 +1,34 @@ +"use strict"; + +module.exports = { + reporter: function (results, data, opts) { + var len = results.length; + var str = ''; + var prevfile; + + opts = opts || {}; + + results.forEach(function (result) { + var file = result.file; + var error = result.error; + + if (prevfile && prevfile !== file) { + str += "\n"; + } + prevfile = file; + + str += file + ': line ' + error.line + ', col ' + + error.character + ', ' + error.reason; + + if (opts.verbose) { + str += ' (' + error.code + ')'; + } + + str += '\n'; + }); + + if (str) { + process.stdout.write(str + "\n" + len + ' error' + ((len === 1) ? '' : 's') + "\n"); + } + } +}; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/jslint_xml.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/jslint_xml.js new file mode 100644 index 000000000..690047176 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/jslint_xml.js @@ -0,0 +1,57 @@ +module.exports = +{ + reporter: function (results) + { + "use strict"; + + var files = {}, + out = [], + pairs = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">" + }, + file, i, issue; + + function encode(s) { + for (var r in pairs) { + if (typeof(s) !== "undefined") { + s = s.replace(new RegExp(r, "g"), pairs[r]); + } + } + return s || ""; + } + + + results.forEach(function (result) { + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + files[result.file].push(result.error); + }); + + out.push(""); + out.push(""); + + for (file in files) { + out.push("\t"); + for (i = 0; i < files[file].length; i++) { + issue = files[file][i]; + out.push("\t\t"); + } + out.push("\t"); + } + + out.push(""); + + process.stdout.write(out.join("\n") + "\n"); + } +}; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/non_error.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/non_error.js new file mode 100644 index 000000000..384ce56b6 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/reporters/non_error.js @@ -0,0 +1,52 @@ +"use strict"; + +module.exports = { + reporter: function (results, data, opts) { + var len = results.length, + str = '', + file, error, globals, unuseds; + + results.forEach(function (result) { + file = result.file; + error = result.error; + str += file + ': line ' + error.line + ', col ' + + error.character + ', ' + error.reason; + + // Add the error code if the --verbose option is set + if (opts.verbose) { + str += ' (' + error.code + ')'; + } + + str += '\n'; + }); + + str += len > 0 ? ("\n" + len + ' error' + ((len === 1) ? '' : 's')) : ""; + + data.forEach(function (data) { + file = data.file; + globals = data.implieds; + unuseds = data.unused; + + if (globals || unuseds) { + str += '\n\n' + file + ' :\n'; + } + + if (globals) { + str += '\tImplied globals:\n'; + globals.forEach(function (global) { + str += '\t\t' + global.name + ': ' + global.line + '\n'; + }); + } + if (unuseds) { + str += '\tUnused Variables:\n\t\t'; + unuseds.forEach(function (unused) { + str += unused.name + '(' + unused.line + '), '; + }); + } + }); + + if (str) { + process.stdout.write(str + "\n"); + } + } +}; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/state.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/state.js new file mode 100644 index 000000000..52ce3872a --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/state.js @@ -0,0 +1,24 @@ +"use strict"; + +var state = { + syntax: {}, + + reset: function () { + this.tokens = { + prev: null, + next: null, + curr: null + }; + + this.option = {}; + this.ignored = {}; + this.directive = {}; + this.jsonMode = false; + this.jsonWarnings = []; + this.lines = []; + this.tab = ""; + this.cache = {}; // Node.JS doesn't have Map. Sniff. + } +}; + +exports.state = state; diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/style.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/style.js new file mode 100644 index 000000000..bb1b3658f --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/style.js @@ -0,0 +1,171 @@ +"use strict"; + +exports.register = function (linter) { + // Check for properties named __proto__. This special property was + // deprecated and then re-introduced for ES6. + + linter.on("Identifier", function style_scanProto(data) { + if (linter.getOption("proto")) { + return; + } + + if (data.name === "__proto__") { + linter.warn("W103", { + line: data.line, + char: data.char, + data: [ data.name ] + }); + } + }); + + // Check for properties named __iterator__. This is a special property + // available only in browsers with JavaScript 1.7 implementation. + + linter.on("Identifier", function style_scanIterator(data) { + if (linter.getOption("iterator")) { + return; + } + + if (data.name === "__iterator__") { + linter.warn("W104", { + line: data.line, + char: data.char, + data: [ data.name ] + }); + } + }); + + // Check for dangling underscores. + + linter.on("Identifier", function style_scanDangling(data) { + if (!linter.getOption("nomen")) { + return; + } + + // Underscore.js + if (data.name === "_") { + return; + } + + // In Node, __dirname and __filename should be ignored. + if (linter.getOption("node")) { + if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) { + return; + } + } + + if (/^(_+.*|.*_+)$/.test(data.name)) { + linter.warn("W105", { + line: data.line, + char: data.from, + data: [ "dangling '_'", data.name ] + }); + } + }); + + // Check that all identifiers are using camelCase notation. + // Exceptions: names like MY_VAR and _myVar. + + linter.on("Identifier", function style_scanCamelCase(data) { + if (!linter.getOption("camelcase")) { + return; + } + + if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) { + linter.warn("W106", { + line: data.line, + char: data.from, + data: [ data.name ] + }); + } + }); + + // Enforce consistency in style of quoting. + + linter.on("String", function style_scanQuotes(data) { + var quotmark = linter.getOption("quotmark"); + var code; + + if (!quotmark) { + return; + } + + // If quotmark is set to 'single' warn about all double-quotes. + + if (quotmark === "single" && data.quote !== "'") { + code = "W109"; + } + + // If quotmark is set to 'double' warn about all single-quotes. + + if (quotmark === "double" && data.quote !== "\"") { + code = "W108"; + } + + // If quotmark is set to true, remember the first quotation style + // and then warn about all others. + + if (quotmark === true) { + if (!linter.getCache("quotmark")) { + linter.setCache("quotmark", data.quote); + } + + if (linter.getCache("quotmark") !== data.quote) { + code = "W110"; + } + } + + if (code) { + linter.warn(code, { + line: data.line, + char: data.char, + }); + } + }); + + linter.on("Number", function style_scanNumbers(data) { + if (data.value.charAt(0) === ".") { + // Warn about a leading decimal point. + linter.warn("W008", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + + if (data.value.substr(data.value.length - 1) === ".") { + // Warn about a trailing decimal point. + linter.warn("W047", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + + if (/^00+/.test(data.value)) { + // Multiple leading zeroes. + linter.warn("W046", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + }); + + // Warn about script URLs. + + linter.on("String", function style_scanJavaScriptURLs(data) { + var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + if (linter.getOption("scripturl")) { + return; + } + + if (re.test(data.value)) { + linter.warn("W107", { + line: data.line, + char: data.char + }); + } + }); +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/node_modules/jshint/src/vars.js b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/vars.js new file mode 100644 index 000000000..327678dd2 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/node_modules/jshint/src/vars.js @@ -0,0 +1,588 @@ +// jshint -W001 + +"use strict"; + +// Identifiers provided by the ECMAScript standard. + +exports.reservedVars = { + arguments : false, + NaN : false +}; + +exports.ecmaIdentifiers = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + "eval" : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Math : false, + Map : false, + Number : false, + Object : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + Set : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false, + WeakMap : false +}; + +// Global variables commonly provided by a web browser environment. + +exports.browser = { + Audio : false, + Blob : false, + addEventListener : false, + applicationCache : false, + atob : false, + blur : false, + btoa : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + CustomEvent : false, + DOMParser : false, + defaultStatus : false, + document : false, + Element : false, + ElementTimeControl : false, + event : false, + FileReader : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement: false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement: false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement: false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Image : false, + length : false, + localStorage : false, + location : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, + MouseEvent : false, + moveBy : false, + moveTo : false, + MutationObserver : false, + name : false, + Node : false, + NodeFilter : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + SVGAElement : false, + SVGAltGlyphDefElement: false, + SVGAltGlyphElement : false, + SVGAltGlyphItemElement: false, + SVGAngle : false, + SVGAnimateColorElement: false, + SVGAnimateElement : false, + SVGAnimateMotionElement: false, + SVGAnimateTransformElement: false, + SVGAnimatedAngle : false, + SVGAnimatedBoolean : false, + SVGAnimatedEnumeration: false, + SVGAnimatedInteger : false, + SVGAnimatedLength : false, + SVGAnimatedLengthList: false, + SVGAnimatedNumber : false, + SVGAnimatedNumberList: false, + SVGAnimatedPathData : false, + SVGAnimatedPoints : false, + SVGAnimatedPreserveAspectRatio: false, + SVGAnimatedRect : false, + SVGAnimatedString : false, + SVGAnimatedTransformList: false, + SVGAnimationElement : false, + SVGCSSRule : false, + SVGCircleElement : false, + SVGClipPathElement : false, + SVGColor : false, + SVGColorProfileElement: false, + SVGColorProfileRule : false, + SVGComponentTransferFunctionElement: false, + SVGCursorElement : false, + SVGDefsElement : false, + SVGDescElement : false, + SVGDocument : false, + SVGElement : false, + SVGElementInstance : false, + SVGElementInstanceList: false, + SVGEllipseElement : false, + SVGExternalResourcesRequired: false, + SVGFEBlendElement : false, + SVGFEColorMatrixElement: false, + SVGFEComponentTransferElement: false, + SVGFECompositeElement: false, + SVGFEConvolveMatrixElement: false, + SVGFEDiffuseLightingElement: false, + SVGFEDisplacementMapElement: false, + SVGFEDistantLightElement: false, + SVGFEFloodElement : false, + SVGFEFuncAElement : false, + SVGFEFuncBElement : false, + SVGFEFuncGElement : false, + SVGFEFuncRElement : false, + SVGFEGaussianBlurElement: false, + SVGFEImageElement : false, + SVGFEMergeElement : false, + SVGFEMergeNodeElement: false, + SVGFEMorphologyElement: false, + SVGFEOffsetElement : false, + SVGFEPointLightElement: false, + SVGFESpecularLightingElement: false, + SVGFESpotLightElement: false, + SVGFETileElement : false, + SVGFETurbulenceElement: false, + SVGFilterElement : false, + SVGFilterPrimitiveStandardAttributes: false, + SVGFitToViewBox : false, + SVGFontElement : false, + SVGFontFaceElement : false, + SVGFontFaceFormatElement: false, + SVGFontFaceNameElement: false, + SVGFontFaceSrcElement: false, + SVGFontFaceUriElement: false, + SVGForeignObjectElement: false, + SVGGElement : false, + SVGGlyphElement : false, + SVGGlyphRefElement : false, + SVGGradientElement : false, + SVGHKernElement : false, + SVGICCColor : false, + SVGImageElement : false, + SVGLangSpace : false, + SVGLength : false, + SVGLengthList : false, + SVGLineElement : false, + SVGLinearGradientElement: false, + SVGLocatable : false, + SVGMPathElement : false, + SVGMarkerElement : false, + SVGMaskElement : false, + SVGMatrix : false, + SVGMetadataElement : false, + SVGMissingGlyphElement: false, + SVGNumber : false, + SVGNumberList : false, + SVGPaint : false, + SVGPathElement : false, + SVGPathSeg : false, + SVGPathSegArcAbs : false, + SVGPathSegArcRel : false, + SVGPathSegClosePath : false, + SVGPathSegCurvetoCubicAbs: false, + SVGPathSegCurvetoCubicRel: false, + SVGPathSegCurvetoCubicSmoothAbs: false, + SVGPathSegCurvetoCubicSmoothRel: false, + SVGPathSegCurvetoQuadraticAbs: false, + SVGPathSegCurvetoQuadraticRel: false, + SVGPathSegCurvetoQuadraticSmoothAbs: false, + SVGPathSegCurvetoQuadraticSmoothRel: false, + SVGPathSegLinetoAbs : false, + SVGPathSegLinetoHorizontalAbs: false, + SVGPathSegLinetoHorizontalRel: false, + SVGPathSegLinetoRel : false, + SVGPathSegLinetoVerticalAbs: false, + SVGPathSegLinetoVerticalRel: false, + SVGPathSegList : false, + SVGPathSegMovetoAbs : false, + SVGPathSegMovetoRel : false, + SVGPatternElement : false, + SVGPoint : false, + SVGPointList : false, + SVGPolygonElement : false, + SVGPolylineElement : false, + SVGPreserveAspectRatio: false, + SVGRadialGradientElement: false, + SVGRect : false, + SVGRectElement : false, + SVGRenderingIntent : false, + SVGSVGElement : false, + SVGScriptElement : false, + SVGSetElement : false, + SVGStopElement : false, + SVGStringList : false, + SVGStylable : false, + SVGStyleElement : false, + SVGSwitchElement : false, + SVGSymbolElement : false, + SVGTRefElement : false, + SVGTSpanElement : false, + SVGTests : false, + SVGTextContentElement: false, + SVGTextElement : false, + SVGTextPathElement : false, + SVGTextPositioningElement: false, + SVGTitleElement : false, + SVGTransform : false, + SVGTransformList : false, + SVGTransformable : false, + SVGURIReference : false, + SVGUnitTypes : false, + SVGUseElement : false, + SVGVKernElement : false, + SVGViewElement : false, + SVGViewSpec : false, + SVGZoomAndPan : false, + TimeEvent : false, + top : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XMLSerializer : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false +}; + +exports.devel = { + alert : false, + confirm: false, + console: false, + Debug : false, + opera : false, + prompt : false +}; + +exports.worker = { + importScripts: true, + postMessage : true, + self : true +}; + +// Widely adopted global names that are not part of ECMAScript standard +exports.nonstandard = { + escape : false, + unescape: false +}; + +// Globals provided by popular JavaScript environments. + +exports.couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false, + provides : false +}; + +exports.node = { + __filename : false, + __dirname : false, + Buffer : false, + console : false, + exports : true, // In Node it is ok to exports = module.exports = foo(); + GLOBAL : false, + global : false, + module : false, + process : false, + require : false, + setTimeout : false, + clearTimeout : false, + setInterval : false, + clearInterval : false, + setImmediate : false, // v0.9.1+ + clearImmediate: false // v0.9.1+ +}; + +exports.phantom = { + phantom : true, + require : true, + WebPage : true, + console : true, // in examples, but undocumented + exports : true // v1.7+ +}; + +exports.rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false +}; + +exports.shelljs = { + target : false, + echo : false, + exit : false, + cd : false, + pwd : false, + ls : false, + find : false, + cp : false, + rm : false, + mv : false, + mkdir : false, + test : false, + cat : false, + sed : false, + grep : false, + which : false, + dirs : false, + pushd : false, + popd : false, + env : false, + exec : false, + chmod : false, + config : false, + error : false, + tempdir : false +}; + +exports.typed = { + ArrayBuffer : false, + ArrayBufferView : false, + DataView : false, + Float32Array : false, + Float64Array : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + Uint8ClampedArray : false +}; + +exports.wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true, + XDomainRequest : true +}; + +// Globals provided by popular JavaScript libraries. + +exports.dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require": false +}; + +exports.jquery = { + "$" : false, + jQuery : false +}; + +exports.mootools = { + "$" : false, + "$$" : false, + Asset : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMEvent : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator: false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false +}; + +exports.prototypejs = { + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false +}; + +exports.yui = { + YUI : false, + Y : false, + YUI_config: false +}; + diff --git a/node_modules/grunt-contrib-jshint/package.json b/node_modules/grunt-contrib-jshint/package.json new file mode 100644 index 000000000..c633d66a7 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/package.json @@ -0,0 +1,61 @@ +{ + "name": "grunt-contrib-jshint", + "description": "Validate files with JSHint.", + "version": "0.6.5", + "homepage": "https://github.com/gruntjs/grunt-contrib-jshint", + "author": { + "name": "Grunt Team", + "url": "http://gruntjs.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/gruntjs/grunt-contrib-jshint.git" + }, + "bugs": { + "url": "https://github.com/gruntjs/grunt-contrib-jshint/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/gruntjs/grunt-contrib-jshint/blob/master/LICENSE-MIT" + } + ], + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "jshint": "~2.1.10" + }, + "devDependencies": { + "grunt-contrib-nodeunit": "~0.1.2", + "grunt-contrib-internal": "~0.4.6", + "grunt": "~0.4.0" + }, + "peerDependencies": { + "grunt": "~0.4.0" + }, + "keywords": [ + "gruntplugin" + ], + "contributors": [ + { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com/" + } + ], + "readme": "# grunt-contrib-jshint v0.6.5 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-jshint.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-jshint)\n\n> Validate files with JSHint.\n\n\n\n## Getting Started\nThis plugin requires Grunt `~0.4.0`\n\nIf you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:\n\n```shell\nnpm install grunt-contrib-jshint --save-dev\n```\n\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\n\n```js\ngrunt.loadNpmTasks('grunt-contrib-jshint');\n```\n\n\n\n\n## Jshint task\n_Run this task with the `grunt jshint` command._\n\nTask targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide.\n\nFor more explanations of the lint errors JSHint will throw at you please visit [jslinterrors.com](http://jslinterrors.com/).\n\n### Options\n\nAny specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options.\n\n[JSHint]: http://www.jshint.com/\n[JSHint documentation]: http://www.jshint.com/docs/\n\nA few additional options are supported:\n\n#### globals\nType: `Object`\nDefault value: `null`\n\nA map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the `JSHINT` function as its third argument. See the [JSHint documentation][] for more information.\n\n#### jshintrc\nType: `String`\nDefault value: `null`\n\nIf this filename is specified, options and globals defined therein will be used. The `jshintrc` file must be valid JSON and looks something like this:\n\n```json\n{\n \"curly\": true,\n \"eqnull\": true,\n \"eqeqeq\": true,\n \"undef\": true,\n \"globals\": {\n \"jQuery\": true\n }\n}\n```\n\n*Be aware that `jshintrc` settings are not merged with your Grunt options.*\n\n#### extensions\nType: `String`\nDefault value: `''`\n\nA list of non-dot-js extensions to check.\n\n#### ignores\nType: `Array`\nDefault value: `null`\n\nA list of files and dirs to ignore. This will override your `.jshintignore` file if set and does not merge.\n\n#### force\nType: `Boolean`\nDefault value: `false`\n\nSet `force` to `true` to report JSHint errors but not fail the task.\n\n#### reporter\nType: `String`\nDefault value: `null`\n\nAllows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: `jslint` or `checkstyle`.\n\nSee also: [Writing your own JSHint reporter.](http://jshint.com/docs/reporters/)\n\n#### reporterOutput\nType: `String`\nDefault value: `null`\n\nSpecify a filepath to output the results of a reporter. If `reporterOutput` is specified then all output will be written to the given filepath instead of printed to stdout.\n\n### Usage examples\n\n#### Wildcards\nIn this example, running `grunt jshint:all` (or `grunt jshint` because `jshint` is a [multi task](http://gruntjs.com/configuring-tasks#task-configuration-and-targets)) will lint the project's Gruntfile as well as all JavaScript files in the `lib` and `test` directories and their subdirectores, using the default JSHint options.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js']\n }\n});\n```\n\n#### Linting before and after concatenating\nIn this example, running `grunt jshint` will lint both the \"beforeconcat\" set and \"afterconcat\" sets of files. This is not ideal, because `dist/output.js` may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) `concat` task.\n\nIn this case, you should lint the \"beforeconcat\" files first, then concat, then lint the \"afterconcat\" files, by running `grunt jshint:beforeconcat concat jshint:afterconcat`.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n concat: {\n dist: {\n src: ['src/foo.js', 'src/bar.js'],\n dest: 'dist/output.js'\n }\n },\n jshint: {\n beforeconcat: ['src/foo.js', 'src/bar.js'],\n afterconcat: ['dist/output.js']\n }\n});\n```\n\n#### Specifying JSHint options and globals\n\nIn this example, custom JSHint options are specified. Note that when `grunt jshint:uses_defaults` is run, those files are linted using the default options, but when `grunt jshint:with_overrides` is run, those files are linted using _merged_ task/target options.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n options: {\n curly: true,\n eqeqeq: true,\n eqnull: true,\n browser: true,\n globals: {\n jQuery: true\n },\n },\n uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'],\n with_overrides: {\n options: {\n curly: false,\n undef: true,\n },\n files: {\n src: ['dir3/**/*.js', 'dir4/**/*.js']\n },\n }\n },\n});\n```\n\n#### Ignoring specific warnings\n\nIf you would like to ignore a specific warning:\n\n```shell\n[L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9.\n```\n\nYou can toggle it by prepending `-` to the warning id as an option:\n\n```js\ngrunt.initConfig({\n jshint: {\n ignore_warning: {\n options: {\n '-W015': true,\n },\n src: ['**/*.js'],\n },\n },\n});\n```\n\n#### Ignoring specific files\n\nOccasionally application files and third party libraries share the same directory. To exclude third party code, but include all current and future application files, use a glob for `files` and specifically exclude libraries using `ignores`. In this example, the jQuery file is matched by the glob but subsequently ignored when JSHint does its analysis.\n\n```js\ngrunt.initConfig({\n jshint: {\n files: ['js/*.js'],\n options: {\n ignores: ['js/jquery.js']\n }\n }\n});\n```\n\n\n## Release History\n\n * 2013-10-23   v0.6.5   Fix output when maxerr is low.\n * 2013-08-29   v0.6.4   jshintrc now loaded by jshint allowing comments.\n * 2013-08-15   v0.6.3   Fix module location for jshint 2.1.10.\n * 2013-07-29   v0.6.2   Update to jshint 2.1.7.\n * 2013-07-27   v0.6.1   Peg jshint to 2.1.4 until breaking changes in 2.1.5 are fixed.\n * 2013-06-02   v0.6.0   Dont always succeed the task when using a custom reporter. Bump jshint to 2.1.3.\n * 2013-05-22   v0.5.4   Fix default reporter to show offending file.\n * 2013-05-19   v0.5.3   Performance: Execute the reporter once rather than per file.\n * 2013-05-18   v0.5.2   Fix printing too many erroneous ignored file errors.\n * 2013-05-17   v0.5.1   Fix for when only 1 file is lint free.\n * 2013-05-17   v0.5.0   Bump to jshint 2.0. Add support for .jshintignore files and ignores option Add support for extensions option. Add support for custom reporters and output report to a file.\n * 2013-04-08   v0.4.3   Fix evaluation of predef option when it's an object.\n * 2013-04-08   v0.4.2   Avoid wiping force option when jshintrc is used.\n * 2013-04-06   v0.4.1   Fix to allow object type for deprecated predef.\n * 2013-04-04   v0.4.0   Revert task level options to override jshintrc files.\n * 2013-03-13   v0.3.0   Bump to JSHint 1.1.0. Add force option to report JSHint errors but not fail the task. Add error/warning code to message. Allow task level options to override jshintrc file.\n * 2013-02-26   v0.2.0   Bump to JSHint 1.0\n * 2013-02-15   v0.1.1   First official release for Grunt 0.4.0.\n * 2013-01-18   v0.1.1rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.\n * 2013-01-09   v0.1.1rc5   Updating to work with grunt v0.4.0rc5. Switching to this.filesSrc api.\n * 2012-10-18   v0.1.0   Work in progress, not yet officially released.\n\n---\n\nTask submitted by [\"Cowboy\" Ben Alman](http://benalman.com/)\n\n*This file was generated on Wed Oct 23 2013 20:33:11.*\n", + "readmeFilename": "README.md", + "_id": "grunt-contrib-jshint@0.6.5", + "dist": { + "shasum": "8a75eeb705242337e4fd3517bbf89c43920817d4" + }, + "_from": "grunt-contrib-jshint@~0.6.4", + "_resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.6.5.tgz" +} diff --git a/node_modules/grunt-contrib-jshint/tasks/jshint.js b/node_modules/grunt-contrib-jshint/tasks/jshint.js new file mode 100644 index 000000000..c9ae207db --- /dev/null +++ b/node_modules/grunt-contrib-jshint/tasks/jshint.js @@ -0,0 +1,74 @@ +/* + * grunt-contrib-jshint + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + var path = require('path'); + var jshint = require('./lib/jshint').init(grunt); + + grunt.registerMultiTask('jshint', 'Validate files with JSHint.', function() { + var done = this.async(); + + // Merge task-specific and/or target-specific options with these defaults. + var options = this.options({ + force: false, + reporterOutput: null, + }); + + // log (verbose) options before hooking in the reporter + grunt.verbose.writeflags(options, 'JSHint options'); + + // Report JSHint errors but dont fail the task + var force = options.force; + delete options.force; + + // Whether to output the report to a file + var reporterOutput = options.reporterOutput; + delete options.reporterOutput; + + // Hook into stdout to capture report + var output = ''; + if (reporterOutput) { + grunt.util.hooker.hook(process.stdout, 'write', { + pre: function(out) { + output += out; + return grunt.util.hooker.preempt(); + } + }); + } + + jshint.lint(this.filesSrc, options, function(results, data) { + var failed = 0; + if (results.length > 0) { + // Fail task if errors were logged except if force was set. + failed = force; + } else { + if (jshint.usingGruntReporter === true && data.length > 0) { + grunt.log.ok(data.length + ' file' + (data.length === 1 ? '' : 's') + ' lint free.'); + } + } + + // Write the output of the reporter if wanted + if (reporterOutput) { + grunt.util.hooker.unhook(process.stdout, 'write'); + reporterOutput = grunt.template.process(reporterOutput); + var destDir = path.dirname(reporterOutput); + if (!grunt.file.exists(destDir)) { + grunt.file.mkdir(destDir); + } + grunt.file.write(reporterOutput, output); + grunt.log.ok('Report "' + reporterOutput + '" created.'); + } + + done(failed); + }); + }); + +}; diff --git a/node_modules/grunt-contrib-jshint/tasks/lib/jshint.js b/node_modules/grunt-contrib-jshint/tasks/lib/jshint.js new file mode 100644 index 000000000..77ba4450d --- /dev/null +++ b/node_modules/grunt-contrib-jshint/tasks/lib/jshint.js @@ -0,0 +1,221 @@ +/* + * grunt-contrib-jshint + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +var path = require('path'); +var jshint = require('jshint').JSHINT; +var jshintcli = require('jshint/src/cli'); + +exports.init = function(grunt) { + var exports = { + usingGruntReporter: false + }; + + // No idea why JSHint treats tabs as options.indent # characters wide, but it + // does. See issue: https://github.com/jshint/jshint/issues/430 + var getTabStr = function(options) { + options = options ? grunt.util._.clone(options) : {}; + options.maxerr = 50; + // Do something that's going to error. + jshint('\tx', options); + // If an error occurred, figure out what character JSHint reported and + // subtract one. + var character = jshint.errors && jshint.errors[0] && jshint.errors[0].character - 1; + // If character is actually a number, use it. Otherwise use 1. + var tabsize = isNaN(character) ? 1 : character; + // If tabsize > 1, return something that should be safe to use as a + // placeholder. \uFFFF repeated 2+ times. + return tabsize > 1 && grunt.util.repeat(tabsize, '\uFFFF'); + }; + + var tabregex = /\t/g; + + // Select a reporter (if not using the default Grunt reporter) + // Copied from jshint/src/cli/cli.js until that part is exposed + exports.selectReporter = function(options) { + switch (true) { + // JSLint reporter + case options.reporter === 'jslint': + case options['jslint-reporter']: + options.reporter = 'jshint/src/reporters/jslint_xml.js'; + break; + + // CheckStyle (XML) reporter + case options.reporter === 'checkstyle': + case options['checkstyle-reporter']: + options.reporter = 'jshint/src/reporters/checkstyle.js'; + break; + + // Reporter that displays additional JSHint data + case options['show-non-errors']: + options.reporter = 'jshint/src/reporters/non_error.js'; + break; + + // Custom reporter + case options.reporter !== undefined: + options.reporter = path.resolve(process.cwd(), options.reporter); + } + + var reporter; + if (options.reporter) { + try { + reporter = require(options.reporter).reporter; + exports.usingGruntReporter = false; + } catch (err) { + grunt.fatal(err); + } + } + + // Use the default Grunt reporter if none are found + if (!reporter) { + reporter = exports.reporter; + exports.usingGruntReporter = true; + } + + return reporter; + }; + + // Default Grunt JSHint reporter + exports.reporter = function(results, data) { + // Dont report empty data as its an ignored file + if (data.length < 1) { + grunt.log.error('0 files linted. Please check your ignored files.'); + return; + } + + if (results.length === 0) { + // Success! + grunt.verbose.ok(); + return; + } + + var options = data[0].options; + + // Tab size as reported by JSHint. + var tabstr = getTabStr(options); + var placeholderregex = new RegExp(tabstr, 'g'); + + // Iterate over all errors. + results.forEach(function(result) { + // Display the defending file + var msg = 'Linting' + (result.file ? ' ' + result.file : '') + ' ...'; + grunt.verbose.write(msg); + + // Something went wrong. + grunt.verbose.or.write(msg); + grunt.log.error(); + + var e = result.error; + // Sometimes there's no error object. + if (!e) { return; } + var pos; + var code = ''; + var evidence = e.evidence; + var character = e.character; + if (evidence) { + // Manually increment errorcount since we're not using grunt.log.error(). + grunt.fail.errorcount++; + // Descriptive code error. + pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + character).yellow + ']'.red; + if (e.code) { + code = e.code.yellow + ':'.red + ' '; + } + grunt.log.writeln(pos + ' ' + code + e.reason.yellow); + // If necessary, eplace each tab char with something that can be + // swapped out later. + if (tabstr) { + evidence = evidence.replace(tabregex, tabstr); + } + if (character === 0) { + // Beginning of line. + evidence = '?'.inverse.red + evidence; + } else if (character > evidence.length) { + // End of line. + evidence = evidence + ' '.inverse.red; + } else { + // Middle of line. + evidence = evidence.slice(0, character - 1) + evidence[character - 1].inverse.red + + evidence.slice(character); + } + // Replace tab placeholder (or tabs) but with a 2-space soft tab. + evidence = evidence.replace(tabstr ? placeholderregex : tabregex, ' '); + grunt.log.writeln(evidence); + } else { + // Generic "Whoops, too many errors" error. + grunt.log.error(e.reason); + } + }); + grunt.log.writeln(); + }; + + // Run JSHint on the given files with the given options + exports.lint = function(files, options, done) { + var cliOptions = { + verbose: grunt.option('verbose'), + extensions: '', + }; + + // A list of non-dot-js extensions to check + if (options.extensions) { + cliOptions.extensions = options.extensions; + delete options.extensions; + } + + // A list ignored files + if (options.ignores) { + if (typeof options.ignores === 'string') { + options.ignores = [options.ignores]; + } + cliOptions.ignores = options.ignores; + delete options.ignores; + } + + // Select a reporter to use + var reporter = exports.selectReporter(options); + + // Remove bad options that may have came in from the cli + ['reporter', 'jslint-reporter', 'checkstyle-reporter', 'show-non-errors'].forEach(function(opt) { + if (options.hasOwnProperty(opt)) { + delete options[opt]; + } + }); + + // Read JSHint options from a specified jshintrc file. + if (options.jshintrc) { + options = jshintcli.loadConfig(options.jshintrc); + delete options.jshintrc; + } + + // Enable/disable debugging if option explicitly set. + if (grunt.option('debug') !== undefined) { + options.devel = options.debug = grunt.option('debug'); + // Tweak a few things. + if (grunt.option('debug')) { + options.maxerr = Infinity; + } + } + + cliOptions.config = options; + + // Run JSHint on all file and collect results/data + var allResults = []; + var allData = []; + var cliopts = grunt.util._.clone(cliOptions); + cliopts.args = files; + cliopts.reporter = function(results, data) { + reporter(results, data); + allResults = allResults.concat(results); + allData = allData.concat(data); + }; + jshintcli.run(cliopts); + done(allResults, allData); + }; + + return exports; +}; diff --git a/node_modules/grunt-contrib-jshint/test/fixtures/dontlint.txt b/node_modules/grunt-contrib-jshint/test/fixtures/dontlint.txt new file mode 100644 index 000000000..8aaf1b4f9 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/test/fixtures/dontlint.txt @@ -0,0 +1 @@ +Dont lint me! \ No newline at end of file diff --git a/node_modules/grunt-contrib-jshint/test/fixtures/lint.txt b/node_modules/grunt-contrib-jshint/test/fixtures/lint.txt new file mode 100644 index 000000000..62b115667 Binary files /dev/null and b/node_modules/grunt-contrib-jshint/test/fixtures/lint.txt differ diff --git a/node_modules/grunt-contrib-jshint/test/fixtures/missingsemicolon.js b/node_modules/grunt-contrib-jshint/test/fixtures/missingsemicolon.js new file mode 100644 index 000000000..2b2ab229e --- /dev/null +++ b/node_modules/grunt-contrib-jshint/test/fixtures/missingsemicolon.js @@ -0,0 +1 @@ +var missingsemicolon = true diff --git a/node_modules/grunt-contrib-jshint/test/fixtures/nodemodule.js b/node_modules/grunt-contrib-jshint/test/fixtures/nodemodule.js new file mode 100644 index 000000000..d0e1f2a3c --- /dev/null +++ b/node_modules/grunt-contrib-jshint/test/fixtures/nodemodule.js @@ -0,0 +1,4 @@ +'use strict'; + +module.exports = function() { +}; diff --git a/node_modules/grunt-contrib-jshint/test/jshint_test.js b/node_modules/grunt-contrib-jshint/test/jshint_test.js new file mode 100644 index 000000000..7ac317669 --- /dev/null +++ b/node_modules/grunt-contrib-jshint/test/jshint_test.js @@ -0,0 +1,141 @@ +'use strict'; + +var path = require('path'); +var grunt = require('grunt'); +var jshint = require('../tasks/lib/jshint').init(grunt); + +var fixtures = path.join(__dirname, 'fixtures'); + +// Helper for testing stdout +var hooker = grunt.util.hooker; +var stdoutEqual = function(callback, done) { + var actual = ''; + // Hook process.stdout.write + hooker.hook(process.stdout, 'write', { + // This gets executed before the original process.stdout.write. + pre: function(result) { + // Concatenate uncolored result onto actual. + actual += grunt.log.uncolor(result); + // Prevent the original process.stdout.write from executing. + return hooker.preempt(); + } + }); + // Execute the logging code to be tested. + callback(); + // Restore process.stdout.write to its original value. + hooker.unhook(process.stdout, 'write'); + // Actually test the actually-logged stdout string to the expected value. + done(actual); +}; + +exports.jshint = { + basic: function(test) { + test.expect(1); + var files = [path.join(fixtures, 'missingsemicolon.js')]; + var options = {}; + jshint.lint(files, options, function(results, data) { + test.equal(results[0].error.reason, 'Missing semicolon.', 'Should reporter a missing semicolon.'); + test.done(); + }); + }, + jshintrc: function(test) { + test.expect(1); + var files = [path.join(fixtures, 'nodemodule.js')]; + var options = { + jshintrc: path.join(__dirname, '..', '.jshintrc') + }; + jshint.lint(files, options, function(results, data) { + test.ok(results.length === 0, 'Should not have reported any errors with supplied .jshintrc'); + test.done(); + }); + }, + defaultReporter: function(test) { + test.expect(2); + grunt.log.muted = false; + var files = [path.join(fixtures, 'nodemodule.js')]; + var options = {}; + stdoutEqual(function() { + jshint.lint(files, options, function(results, data) {}); + }, function(result) { + test.ok(jshint.usingGruntReporter, 'Should be using the default grunt reporter.'); + test.ok(result.indexOf('[L3:C1] W117: \'module\' is not defined.') !== -1, 'Should have reported errors with the default grunt reporter.'); + test.done(); + }); + }, + defaultReporterErrors: function(test) { + test.expect(3); + grunt.log.muted = false; + var files = [path.join(fixtures, 'nodemodule.js'), path.join(fixtures, 'missingsemicolon.js')]; + var options = {}; + stdoutEqual(function() { + jshint.lint(files, options, function(results, data) {}); + }, function(result) { + test.ok(jshint.usingGruntReporter, 'Should be using the default grunt reporter.'); + test.ok(result.match(/nodemodule\.js\s\.\.\.ERROR/g).length === 2, 'Should have reported nodemodule.js once per error.'); + test.ok(result.match(/missingsemicolon\.js\s\.\.\.ERROR/g).length === 1, 'Should have reported missingsemicolon.js once per error.'); + test.done(); + }); + }, + alternateReporter: function(test) { + test.expect(2); + var files = [path.join(fixtures, 'nodemodule.js')]; + var options = { + reporter: 'jslint' + }; + stdoutEqual(function() { + jshint.lint(files, options, function(results, data) {}); + }, function(result) { + test.ok((jshint.usingGruntReporter === false), 'Should NOT be using the default grunt reporter.'); + test.ok(result.indexOf('') !== -1, 'Should have reported errors with the jslint reporter.'); + test.done(); + }); + }, + reporterOutput: function(test) { + test.expect(1); + var result = grunt.file.read(path.join('tmp', 'report.xml')); + test.ok(result.indexOf('') !== -1, 'Should have reported errors with the checkstyle reporter.'); + test.done(); + }, + dontBlowUp: function(test) { + test.expect(1); + var files = [path.join(fixtures, 'lint.txt')]; + jshint.lint(files, {}, function(results, data) { + test.equal(results[0].error.code, 'W100', 'It should not blow up if an error occurs on character 0.'); + test.done(); + }); + }, + jshintignore: function(test) { + test.expect(1); + var files = [path.join(fixtures, 'dontlint.txt')]; + jshint.lint(files, {}, function(results, data) { + test.equal(data.length, 0, 'Should not have linted a file listed in the .jshintignore.'); + test.done(); + }); + }, + ignoresOption: function(test) { + test.expect(1); + var files = [path.join(fixtures, 'lint.txt')]; + var options = { + ignores: files + }; + jshint.lint(files, options, function(results, data) { + test.equal(data.length, 0, 'Should not have linted a file listed in the ignores option.'); + test.done(); + }); + }, + singleReportCall: function(test) { + test.expect(2); + + // stub jshint.reporter + var reporterCallCount = 0; + var _report = jshint.reporter; + jshint.reporter = function() { reporterCallCount++; }; + + var files = [path.join(fixtures, 'dontlint.txt'), path.join(fixtures, 'lint.txt')]; + jshint.lint(files, {}, function(results, data) { + test.equal(data.length, 1, 'Should not have linted a file listed in the .jshintignore.'); + test.equal(reporterCallCount, 1, 'Should have called the reporter once.'); + test.done(); + }); + } +}; diff --git a/node_modules/grunt-contrib-less/.jshintrc b/node_modules/grunt-contrib-less/.jshintrc new file mode 100644 index 000000000..fc19146d9 --- /dev/null +++ b/node_modules/grunt-contrib-less/.jshintrc @@ -0,0 +1,13 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/.npmignore b/node_modules/grunt-contrib-less/.npmignore new file mode 100644 index 000000000..5cb6bfd4d --- /dev/null +++ b/node_modules/grunt-contrib-less/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/.travis.yml b/node_modules/grunt-contrib-less/.travis.yml new file mode 100644 index 000000000..57661910e --- /dev/null +++ b/node_modules/grunt-contrib-less/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/AUTHORS b/node_modules/grunt-contrib-less/AUTHORS new file mode 100644 index 000000000..bd3004e2b --- /dev/null +++ b/node_modules/grunt-contrib-less/AUTHORS @@ -0,0 +1,9 @@ +Tyler Kellen (http://goingslowly.com/) +"Cowboy" Ben Alman (http://benalman.com/) +Chris Talkington (http://christalkington.com/) +Teddy Cross (http://tkaz.ec/) +Justin Searls (http://about.me/searls/) +Thomas Boyt (http://www.thomasboyt.com/) +Jake Harding (http://thejakeharding.com/) +Jason Karns (http://jasonkarns.com/) +Sebastian Tschan (https://blueimp.net/) diff --git a/node_modules/grunt-contrib-less/CHANGELOG b/node_modules/grunt-contrib-less/CHANGELOG new file mode 100644 index 000000000..4a1e7c958 --- /dev/null +++ b/node_modules/grunt-contrib-less/CHANGELOG @@ -0,0 +1,88 @@ +v0.8.2: + date: 2013-11-14 + changes: + - Support outputSourceFiles +v0.8.1: + date: 2013-10-24 + changes: + - Support sourceMapFilename, sourceMapBasepath and sourceMapRootpath +v0.8.0: + date: 2013-10-22 + changes: + - Upgrade to LESS 1.5 + - Support strictUnits option + - Support sourceMap option + - Add customFunctions option for defining custom functions within LESS + - Output the source file name on error + - yuicompress option now cleancss (Less changed underlying dependency) +v0.7.0: + date: 2013-08-08 + changes: + - Downgrade no source files warning to only in verbose mode +v0.6.5: + date: 2013-08-08 + changes: + - Support strictMath option + - Support rootpath parse option +v0.6.4: + date: 2013-07-09 + changes: + - Support relativeUrls option +v0.6.3: + date: 2013-07-06 + changes: + - Add report option for minification and gzip results +v0.6.2: + date: 2013-07-03 + changes: + - support syncImport +v0.6.1: + date: 2013-06-12 + changes: + - Support ieCompat +v0.6.0: + date: 2013-06-09 + changes: + - Bump less to 1.4.0 +v0.5.2: + date: 2013-05-23 + changes: + - Improve error handling. +v0.5.1: + date: 2013-04-25 + changes: + - Gracefully handle configuration without sources. +v0.5.0: + date: 2013-02-15 + changes: + - First official release for Grunt 0.4.0. +v0.5.0rc7: + date: 2013-01-23 + changes: + - Updating grunt/gruntplugin dependencies to rc7. + - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. + - Remove experimental wildcard destination support. + - Switching to this.files api. +v0.3.2: + date: 2012-10-18 + changes: + - Add support for dumpLineNumbers. +v0.3.1: + date: 2012-10-12 + changes: + - Rename grunt-contrib-lib dep to grunt-lib-contrib. +v0.3.0: + date: 2012-09-24 + changes: + - Global options depreciated + - Revert normalize linefeeds. +v0.2.2: + date: 2012-09-16 + changes: + - Support all less options + - Normalize linefeeds + - Default path to dirname of src file. +v0.2.0: + date: 2012-09-10 + changes: + - Refactored from grunt-contrib into individual repo. diff --git a/node_modules/grunt-contrib-less/CONTRIBUTING.md b/node_modules/grunt-contrib-less/CONTRIBUTING.md new file mode 100644 index 000000000..5d08cc387 --- /dev/null +++ b/node_modules/grunt-contrib-less/CONTRIBUTING.md @@ -0,0 +1 @@ +Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project. diff --git a/node_modules/grunt-contrib-less/Gruntfile.js b/node_modules/grunt-contrib-less/Gruntfile.js new file mode 100644 index 000000000..7fe3fd0f9 --- /dev/null +++ b/node_modules/grunt-contrib-less/Gruntfile.js @@ -0,0 +1,196 @@ +/* + * grunt-contrib-less + * http://gruntjs.com/ + * + * Copyright (c) 2013 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'tasks/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + } + }, + + // Before generating any new files, remove any previously-created files. + clean: { + tests: ['tmp'] + }, + + // Configuration to be run (and then tested). + less: { + compile: { + options: { + paths: ['test/fixtures/include'] + }, + files: { + 'tmp/less.css': ['test/fixtures/style.less'], + 'tmp/concat.css': ['test/fixtures/style.less', 'test/fixtures/style2.less', 'test/fixtures/style3.less'] + } + }, + compress: { + options: { + paths: ['test/fixtures/include'], + compress: true + }, + files: { + 'tmp/compress.css': ['test/fixtures/style.less'] + } + }, + nopaths: { + files: { + 'tmp/nopaths.css': ['test/fixtures/nopaths.less'] + } + }, + cleancss: { + options: { + paths: ['test/fixtures/include'], + cleancss: true + }, + files: { + 'tmp/cleancss.css': ['test/fixtures/style.less'] + } + }, + ieCompatTrue: { + options: { + paths: ['test/fixtures/include'], + ieCompat: true + }, + files: { + 'tmp/ieCompatTrue.css': ['test/fixtures/ieCompat.less'] + } + }, + ieCompatFalse: { + options: { + paths: ['test/fixtures/include'], + ieCompat: false + }, + files: { + 'tmp/ieCompatFalse.css': ['test/fixtures/ieCompat.less'] + } + }, + nofiles: { + }, + nomatchedfiles: { + files: { "tmp/nomatchedfiles.css" : 'test/nonexistent/*.less' } + }, + compressReport: { + options: { + paths: ['test/fixtures/include'], + compress: true, + report: 'min' + }, + files: { + 'tmp/compressReport.css': ['test/fixtures/style.less', 'test/fixtures/style2.less'] + } + }, + cleancssReport: { + options: { + paths: ['test/fixtures/include'], + cleancss: true, + report: 'gzip' + }, + files: { + 'tmp/cleancssReport.css': ['test/fixtures/style.less', 'test/fixtures/style2.less', 'test/fixtures/style3.less'] + } + }, + variablesAsLess: { + src: 'test/fixtures/variablesAsLess.less', + dest: 'tmp/variablesAsLess.css', + }, + sourceMap: { + options: { + sourceMap: true, + }, + src: 'test/fixtures/style3.less', + dest: 'tmp/sourceMap.css', + }, + sourceMapFilename: { + options: { + sourceMap: true, + sourceMapFilename: 'tmp/sourceMapFilename.css.map' + }, + src: 'test/fixtures/style3.less', + dest: 'tmp/sourceMapFilename.css', + }, + sourceMapBasepath: { + options: { + sourceMap: true, + sourceMapFilename: 'tmp/sourceMapBasepath.css.map', + sourceMapBasepath: 'test/fixtures/' + }, + src: 'test/fixtures/style3.less', + dest: 'tmp/sourceMapBasepath.css', + }, + sourceMapRootpath: { + options: { + sourceMap: true, + sourceMapFilename: 'tmp/sourceMapRootpath.css.map', + sourceMapRootpath: 'http://example.org/' + }, + src: 'test/fixtures/style3.less', + dest: 'tmp/sourceMapRootpath.css', + }, + sourceMapLessInline: { + options: { + sourceMap: true, + sourceMapFilename: 'tmp/sourceMapLessInline.css.map', + outputSourceFiles: true, + }, + src: 'test/fixtures/style3.less', + dest: 'tmp/sourceMapLessInline.css', + }, + testCustomFunctions: { + options: { + customFunctions: { + 'get-color': function(less, color) { + return 'red'; + }, + 'multiple-args': function(less, arg1, arg2) { + return (((arg1.value * 1) + (arg2.value))) + arg1.unit.numerator[0]; + }, + 'string-result': function(less, arg1) { + return "\"Hello\""; + } + } + }, + files: { + 'tmp/customFunctions.css': ['test/fixtures/customFunctions.less'] + } + }, + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'] + } + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-internal'); + + // Whenever the "test" task is run, first clean the "tmp" dir, then run this + // plugin's task(s), then test the result. + grunt.registerTask('test', ['clean', 'less', 'nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test', 'build-contrib']); + +}; diff --git a/node_modules/grunt-contrib-less/LICENSE-MIT b/node_modules/grunt-contrib-less/LICENSE-MIT new file mode 100644 index 000000000..857ddc0ae --- /dev/null +++ b/node_modules/grunt-contrib-less/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2013 Tyler Kellen, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/README.md b/node_modules/grunt-contrib-less/README.md new file mode 100644 index 000000000..ec2072a84 --- /dev/null +++ b/node_modules/grunt-contrib-less/README.md @@ -0,0 +1,205 @@ +# grunt-contrib-less v0.8.2 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-less.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-less) + +> Compile LESS files to CSS. + + + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-contrib-less --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-contrib-less'); +``` + +*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-less/tree/grunt-0.3-stable).* + + +## Less task +_Run this task with the `grunt less` command._ + +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. +### Options + +#### paths +Type: `String|Array` +Default: Directory of input file. + +Specifies directories to scan for @import directives when parsing. Default value is the directory of the source, which is probably what you want. + +#### compress +Type: `Boolean` +Default: `false` + +Compress output by removing some whitespaces. + +#### cleancss +Type: `Boolean` +Default: `false` + +Compress output using [clean-css](https://npmjs.org/package/clean-css). + +#### ieCompat +Type: `Boolean` +Default: `true` + +Enforce the css output is compatible with Internet Explorer 8. + +For example, the [data-uri](https://github.com/cloudhead/less.js/pull/1086) function encodes a file in base64 encoding and embeds it into the generated CSS files as a data-URI. Because Internet Explorer 8 limits `data-uri`s to 32KB, the [ieCompat](https://github.com/cloudhead/less.js/pull/1190) option prevents `less` from exceeding this. + +#### optimization +Type: `Integer` +Default: `null` + +Set the parser's optimization level. The lower the number, the less nodes it will create in the tree. This could matter for debugging, or if you want to access the individual nodes in the tree. + +#### strictImports +Type: `Boolean` +Default: `false` + +Force evaluation of imports. + +#### strictMath +Type: `Boolean` +Default: `false` + +When enabled, math is required to be in parenthesis. + +#### strictUnits +Type: `Boolean` +Default: `false` + +When enabled, less will validate the units used (e.g. 4px/2px = 2, not 2px and 4em/2px throws an error). + +#### syncImport +Type: `Boolean` +Default: `false` + +Read @import'ed files synchronously from disk. + +#### dumpLineNumbers +Type: `String` +Default: `false` + +Configures -sass-debug-info support. + +Accepts following values: `comments`, `mediaquery`, `all`. + +#### relativeUrls +Type: `Boolean` +Default: `false` + +Rewrite urls to be relative. false: do not modify urls. + +#### customFunctions +Type: `Object` +Default: none + +Define custom functions to be available within your LESS stylesheets. The function's name must be lowercase and +return a primitive type (not an object or array). In the function definition, the first argument is the less +object, and subsequent arguments are from the less function call. Values passed to the function are not simple +primitive types, rather types defined within less. See the LESS documentation for more information on the available types. + +#### report +Choices: `false` `'min'` `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Less is performing, but using `'gzip'` can add 5-10x runtime task execution. + +Example ouput using `'gzip'`: + +``` +Original: 198444 bytes. +Minified: 101615 bytes. +Gzipped: 20084 bytes. +``` + +#### sourceMap +Type: `Boolean` +Default: `false` + +Enable source maps. + +#### sourceMapFilename +Type: `String` +Default: none + +Write the source map to a separate file with the given filename. + +#### sourceMapBasepath +Type: `String` +Default: none + +Sets the base path for the less file paths in the source map. + +#### sourceMapRootpath +Type: `String` +Default: none + +Adds this path onto the less file paths in the source map. + +#### outputSourceFiles +Type: `Boolean` +Default: false + +Puts the less files into the map instead of referencing them. + +### Usage Examples + +```js +less: { + development: { + options: { + paths: ["assets/css"] + }, + files: { + "path/to/result.css": "path/to/source.less" + } + }, + production: { + options: { + paths: ["assets/css"], + cleancss: true + }, + files: { + "path/to/result.css": "path/to/source.less" + } + } +} +``` + + +## Release History + + * 2013-11-14   v0.8.2   Support outputSourceFiles + * 2013-10-24   v0.8.1   Support sourceMapFilename, sourceMapBasepath and sourceMapRootpath + * 2013-10-22   v0.8.0   Upgrade to LESS 1.5 Support strictUnits option Support sourceMap option Add customFunctions option for defining custom functions within LESS Output the source file name on error yuicompress option now cleancss (Less changed underlying dependency) + * 2013-08-08   v0.7.0   Downgrade no source files warning to only in verbose mode + * 2013-08-08   v0.6.5   Support strictMath option Support rootpath parse option + * 2013-07-09   v0.6.4   Support relativeUrls option + * 2013-07-06   v0.6.3   Add report option for minification and gzip results + * 2013-07-03   v0.6.2   support syncImport + * 2013-06-12   v0.6.1   Support ieCompat + * 2013-06-09   v0.6.0   Bump less to 1.4.0 + * 2013-05-23   v0.5.2   Improve error handling. + * 2013-04-25   v0.5.1   Gracefully handle configuration without sources. + * 2013-02-15   v0.5.0   First official release for Grunt 0.4.0. + * 2013-01-23   v0.5.0rc7   Updating grunt/gruntplugin dependencies to rc7. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. Remove experimental wildcard destination support. Switching to this.files api. + * 2012-10-18   v0.3.2   Add support for dumpLineNumbers. + * 2012-10-12   v0.3.1   Rename grunt-contrib-lib dep to grunt-lib-contrib. + * 2012-09-24   v0.3.0   Global options depreciated Revert normalize linefeeds. + * 2012-09-16   v0.2.2   Support all less options Normalize linefeeds Default path to dirname of src file. + * 2012-09-10   v0.2.0   Refactored from grunt-contrib into individual repo. + +--- + +Task submitted by [Tyler Kellen](http://goingslowly.com/) + +*This file was generated on Thu Nov 14 2013 09:29:34.* diff --git a/node_modules/grunt-contrib-less/docs/less-examples.md b/node_modules/grunt-contrib-less/docs/less-examples.md new file mode 100644 index 000000000..a18418b60 --- /dev/null +++ b/node_modules/grunt-contrib-less/docs/less-examples.md @@ -0,0 +1,23 @@ +# Usage Examples + +```js +less: { + development: { + options: { + paths: ["assets/css"] + }, + files: { + "path/to/result.css": "path/to/source.less" + } + }, + production: { + options: { + paths: ["assets/css"], + cleancss: true + }, + files: { + "path/to/result.css": "path/to/source.less" + } + } +} +``` diff --git a/node_modules/grunt-contrib-less/docs/less-options.md b/node_modules/grunt-contrib-less/docs/less-options.md new file mode 100644 index 000000000..b1e9c98bc --- /dev/null +++ b/node_modules/grunt-contrib-less/docs/less-options.md @@ -0,0 +1,124 @@ +# Options + +## paths +Type: `String|Array` +Default: Directory of input file. + +Specifies directories to scan for @import directives when parsing. Default value is the directory of the source, which is probably what you want. + +## compress +Type: `Boolean` +Default: `false` + +Compress output by removing some whitespaces. + +## cleancss +Type: `Boolean` +Default: `false` + +Compress output using [clean-css](https://npmjs.org/package/clean-css). + +## ieCompat +Type: `Boolean` +Default: `true` + +Enforce the css output is compatible with Internet Explorer 8. + +For example, the [data-uri](https://github.com/cloudhead/less.js/pull/1086) function encodes a file in base64 encoding and embeds it into the generated CSS files as a data-URI. Because Internet Explorer 8 limits `data-uri`s to 32KB, the [ieCompat](https://github.com/cloudhead/less.js/pull/1190) option prevents `less` from exceeding this. + +## optimization +Type: `Integer` +Default: `null` + +Set the parser's optimization level. The lower the number, the less nodes it will create in the tree. This could matter for debugging, or if you want to access the individual nodes in the tree. + +## strictImports +Type: `Boolean` +Default: `false` + +Force evaluation of imports. + +## strictMath +Type: `Boolean` +Default: `false` + +When enabled, math is required to be in parenthesis. + +## strictUnits +Type: `Boolean` +Default: `false` + +When enabled, less will validate the units used (e.g. 4px/2px = 2, not 2px and 4em/2px throws an error). + +## syncImport +Type: `Boolean` +Default: `false` + +Read @import'ed files synchronously from disk. + +## dumpLineNumbers +Type: `String` +Default: `false` + +Configures -sass-debug-info support. + +Accepts following values: `comments`, `mediaquery`, `all`. + +## relativeUrls +Type: `Boolean` +Default: `false` + +Rewrite urls to be relative. false: do not modify urls. + +## customFunctions +Type: `Object` +Default: none + +Define custom functions to be available within your LESS stylesheets. The function's name must be lowercase and +return a primitive type (not an object or array). In the function definition, the first argument is the less +object, and subsequent arguments are from the less function call. Values passed to the function are not simple +primitive types, rather types defined within less. See the LESS documentation for more information on the available types. + +## report +Choices: `false` `'min'` `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Less is performing, but using `'gzip'` can add 5-10x runtime task execution. + +Example ouput using `'gzip'`: + +``` +Original: 198444 bytes. +Minified: 101615 bytes. +Gzipped: 20084 bytes. +``` + +## sourceMap +Type: `Boolean` +Default: `false` + +Enable source maps. + +## sourceMapFilename +Type: `String` +Default: none + +Write the source map to a separate file with the given filename. + +## sourceMapBasepath +Type: `String` +Default: none + +Sets the base path for the less file paths in the source map. + +## sourceMapRootpath +Type: `String` +Default: none + +Adds this path onto the less file paths in the source map. + +## outputSourceFiles +Type: `Boolean` +Default: false + +Puts the less files into the map instead of referencing them. diff --git a/node_modules/grunt-contrib-less/docs/less-overview.md b/node_modules/grunt-contrib-less/docs/less-overview.md new file mode 100644 index 000000000..f0c452b99 --- /dev/null +++ b/node_modules/grunt-contrib-less/docs/less-overview.md @@ -0,0 +1 @@ +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/docs/overview.md b/node_modules/grunt-contrib-less/docs/overview.md new file mode 100644 index 000000000..02a30fa95 --- /dev/null +++ b/node_modules/grunt-contrib-less/docs/overview.md @@ -0,0 +1 @@ +*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-less/tree/grunt-0.3-stable).* \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/.bin/lessc b/node_modules/grunt-contrib-less/node_modules/.bin/lessc new file mode 120000 index 000000000..87a5294c1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/.bin/lessc @@ -0,0 +1 @@ +../less/bin/lessc \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.gitattributes b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.gitattributes new file mode 100644 index 000000000..176a458f9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.jshintrc b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.jshintrc new file mode 100644 index 000000000..e0cc7bbe8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.jshintrc @@ -0,0 +1,14 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true, + "es5": true +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.npmignore b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.npmignore new file mode 100644 index 000000000..5cb6bfd4d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.travis.yml b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.travis.yml new file mode 100644 index 000000000..f2c257a22 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_install: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/AUTHORS b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/AUTHORS new file mode 100644 index 000000000..5de1a921c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/AUTHORS @@ -0,0 +1,4 @@ +Tyler Kellen (http://goingslowly.com/) +Chris Talkington (http://christalkington.com/) +Larry Davis (http://lazd.net/) +Sindre Sorhus (http://sindresorhus.com) diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/CHANGELOG b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/CHANGELOG new file mode 100644 index 000000000..f1e4c303c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/CHANGELOG @@ -0,0 +1,47 @@ +v0.6.1: + date: 2013-03-24 + changes: + - Add formatForType option +v0.6.0: + date: 2013-03-14 + changes: + - Change API/reportying style for minMaxInfo +v0.5.3: + date: 2013-02-23 + changes: + - use MIT licensed zlib-browserify instead of unlicensed gzip-js +v0.5.2: + date: 2013-01-24 + changes: + - add minMaxGzip & minMaxInfo. +v0.5.0: + date: 2012-12-05 + changes: + - remove findBasePath, buildIndividualDest and isIndividualDest. + - remove options and normalizeMultiTaskFiles. + - remove node v0.6 and grunt v0.3 support. +v0.4.0: + date: 2012-11-20 + changes: + - findBasePath returns '' if passed false. + - Added stripPath. +v0.3.1: + date: 2012-10-29 + changes: + - Tweaked findBasePath to handle single dot differently. + - Start testing with Travis. + - Docs cleanup. +v0.3.0: + date: 2012-09-24 + changes: + - Added findBasePath, buildIndividualDest, isIndividualDest, optsToArgs. + - Refactored tests. + - Automatically parse templates in options. +v0.2.1: + date: 2012-09-14 + changes: + - Added non-destuctive namespace declarations. +v0.2.0: + date: 2012-09-10 + changes: + - Refactored from grunt-contrib into individual repo. diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/Gruntfile.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/Gruntfile.js new file mode 100644 index 000000000..6e602bba7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/Gruntfile.js @@ -0,0 +1,60 @@ +/* + * grunt-lib-contrib + * http://gruntjs.com/ + * + * Copyright (c) 2012 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +module.exports = function(grunt) { + 'use strict'; + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'lib/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + } + }, + + test_vars: { + source: 'source/' + }, + + test_task: { + options: { + param: 'task', + param2: 'task', + template: '<%= test_vars.source %>', + data: { + template: ['<%= test_vars.source %>'] + } + }, + target: { + options: { + param: 'target' + } + } + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'] + } + }); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + + // Whenever the "test" task is run, then test the result. + grunt.registerTask('test', ['nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test']); +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/LICENSE-MIT b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/LICENSE-MIT new file mode 100644 index 000000000..358b067ad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Tyler Kellen, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/README.md b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/README.md new file mode 100644 index 000000000..88116eb48 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/README.md @@ -0,0 +1,65 @@ +# grunt-lib-contrib [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-lib-contrib.png?branch=master)](http://travis-ci.org/gruntjs/grunt-lib-contrib) + +> Common functionality shared across grunt-contrib tasks. + +The purpose of grunt-lib-contrib is to explore solutions to common problems task writers encounter, and to ease the upgrade path for contrib tasks. + +**These APIs should be considered highly unstable. Depend on them at your own risk!** + +_Over time, some of the functionality provided here may be incorporated directly into grunt for mainstream use. Until then, you may require `grunt-lib-contrib` as a dependency in your projects, but be very careful to specify an exact version number instead of a range, as backwards-incompatible changes are likely to be introduced._ + +### Helper Functions + +#### getNamespaceDeclaration(ns) + +This helper is used to build JS namespace declarations. + +#### optsToArgs(options) + +Convert an object to an array of CLI arguments, which can be used with `child_process.spawn()`. + +```js +// Example +{ + fooBar: 'a', // ['--foo-bar', 'a'] + fooBar: 1, // ['--foo-bar', '1'] + fooBar: true, // ['--foo-bar'] + fooBar: false, // + fooBar: ['a', 'b'] // ['--foo-bar', 'a', '--foo-bar', 'b'] +} +``` + +#### stripPath(pth, strip) + +Strip a path from a path. normalize both paths for best results. + +#### minMaxInfo(min, max, report) + +Helper for logging compressed, uncompressed and gzipped sizes of strings. + +#### report +Choices: `false`, `'min'`, `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. + +**Important** Including `'gzip'` results can make this task 5-10x slower depending on the size of the file. + + +```js +var max = grunt.file.read('max.js'); +var min = minify(max); +minMaxInfo(min, max, 'gzip'); +``` + +Would print: + +``` +Original: 495 bytes. +Minified: 396 bytes. +Gzipped: 36 bytes. +``` + +-- + +*Lib submitted by [Tyler Kellen](https://goingslowly.com/).* \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/lib/contrib.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/lib/contrib.js new file mode 100644 index 000000000..9dcf9455a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/lib/contrib.js @@ -0,0 +1,111 @@ +/* + * grunt-lib-contrib + * http://gruntjs.com/ + * + * Copyright (c) 2012 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +exports.init = function(grunt) { + 'use strict'; + + var exports = {}; + + var path = require('path'); + + exports.getNamespaceDeclaration = function(ns) { + var output = []; + var curPath = 'this'; + if (ns !== 'this') { + var nsParts = ns.split('.'); + nsParts.forEach(function(curPart, index) { + if (curPart !== 'this') { + curPath += '[' + JSON.stringify(curPart) + ']'; + output.push(curPath + ' = ' + curPath + ' || {};'); + } + }); + } + + return { + namespace: curPath, + declaration: output.join('\n') + }; + }; + + // Convert an object to an array of CLI arguments + exports.optsToArgs = function(options) { + var args = []; + + Object.keys(options).forEach(function(flag) { + var val = options[flag]; + + flag = flag.replace(/[A-Z]/g, function(match) { + return '-' + match.toLowerCase(); + }); + + if (val === true) { + args.push('--' + flag); + } + + if (grunt.util._.isString(val)) { + args.push('--' + flag, val); + } + + if (grunt.util._.isNumber(val)) { + args.push('--' + flag, '' + val); + } + + if (grunt.util._.isArray(val)) { + val.forEach(function(arrVal) { + args.push('--' + flag, arrVal); + }); + } + }); + + return args; + }; + + // Strip a path from a path. normalize both paths for best results. + exports.stripPath = function(pth, strip) { + if (strip && strip.length >= 1) { + strip = path.normalize(strip); + pth = path.normalize(pth); + pth = grunt.util._(pth).strRight(strip); + pth = grunt.util._(pth).ltrim(path.sep); + } + + return pth; + }; + + // Log min and max info + function gzipSize(src) { + return src ? require('zlib-browserify').gzipSync(src).length : 0; + } + exports.minMaxInfo = function(min, max, report) { + if (report === 'min' || report === 'gzip') { + grunt.log.writeln('Original: ' + String(max.length).green + ' bytes.'); + grunt.log.writeln('Minified: ' + String(min.length).green + ' bytes.'); + } + if (report === 'gzip') { + // Note this option is pretty slow so it is not enabled by default + grunt.log.write('Gzipped: '); + grunt.log.writeln(String(gzipSize(min)).green + ' bytes.'); + } + }; + + exports.formatForType = function(string, type, namespace, filename) { + namespace = namespace || false; + + if (type === 'amd' && namespace === false) { + string = 'return ' + string; + } else if (type === 'commonjs' && namespace === false) { + string = 'module.exports = ' + string; + } else if (type === 'amd' && namespace !== false || type === 'commonjs' && namespace !== false || type === 'js' && namespace !== false) { + string = namespace+'['+JSON.stringify(filename)+'] = '+string+';'; + } + + return string; + }; + + return exports; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js new file mode 100644 index 000000000..66740432b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js @@ -0,0 +1,43 @@ +const Zlib = module.exports = require('./zlib'); + +// the least I can do is make error messages for the rest of the node.js/zlib api. +// (thanks, dominictarr) +function error () { + var m = [].slice.call(arguments).join(' ') + throw new Error([ + m, + 'we accept pull requests', + 'http://github.com/brianloveswords/zlib-browserify' + ].join('\n')) +} + +;['createGzip' +, 'createGunzip' +, 'createDeflate' +, 'createDeflateRaw' +, 'createInflate' +, 'createInflateRaw' +, 'createUnzip' +, 'Gzip' +, 'Gunzip' +, 'Inflate' +, 'InflateRaw' +, 'Deflate' +, 'DeflateRaw' +, 'Unzip' +, 'inflateRaw' +, 'deflateRaw'].forEach(function (name) { + Zlib[name] = function () { + error('sorry,', name, 'is not implemented yet') + } +}); + +const _deflate = Zlib.deflate; +const _gzip = Zlib.gzip; + +Zlib.deflate = function deflate(stringOrBuffer, callback) { + return _deflate(Buffer(stringOrBuffer), callback); +}; +Zlib.gzip = function gzip(stringOrBuffer, callback) { + return _gzip(Buffer(stringOrBuffer), callback); +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json new file mode 100644 index 000000000..3d13d8335 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json @@ -0,0 +1,40 @@ +{ + "name": "zlib-browserify", + "version": "0.0.1", + "description": "Wrapper for zlib.js to allow for browserifyication", + "main": "index.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.3" + }, + "scripts": { + "test": "./node_modules/tap test/*.test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/zlib-browserify.git" + }, + "keywords": [ + "zlib", + "browserify" + ], + "author": { + "name": "Brian J. Brennan" + }, + "license": "MIT", + "gitHead": "4be9419f0e8e9dec9629c8a538b33a4efd7df17b", + "readmeFilename": "readme.md", + "readme": "Zlib in yo' browser.\n", + "bugs": { + "url": "https://github.com/brianloveswords/zlib-browserify/issues" + }, + "_id": "zlib-browserify@0.0.1", + "dist": { + "shasum": "f8882b91bd8aa91b5e5a532425309da9f5c0d878" + }, + "_from": "zlib-browserify@0.0.1", + "_resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md new file mode 100644 index 000000000..ca4a5eeaa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md @@ -0,0 +1 @@ +Zlib in yo' browser. diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js new file mode 100644 index 000000000..5b7a3ce39 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js @@ -0,0 +1,65 @@ +const test = require('tap').test; +const zlibA = require('zlib'); +const zlibB = require('..'); +const crypto = require('crypto'); + +test('zlibA.deflate -> zlibB.inflate', function (t) { + const expect = crypto.randomBytes(1024); + zlibA.deflate(expect, function (err, cmpA) { + zlibB.inflate(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.deflate -> zlibA.inflate', function (t) { + const expect = crypto.randomBytes(1024); + zlibB.deflate(expect, function (err, cmpA) { + zlibA.inflate(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.deflate -> zlibA.inflate (string)', function (t) { + const expect = 'ohaihihihihihihihihihihihihihihihi'; + zlibB.deflate(expect, function (err, cmpA) { + zlibA.inflate(cmpA, function (err, result) { + t.same(result.toString(), expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibA.gzip -> zlibB.gunzip', function (t) { + const expect = crypto.randomBytes(1024); + zlibA.gzip(expect, function (err, cmpA) { + zlibB.gunzip(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.gzip -> zlibA.gunzip', function (t) { + const expect = crypto.randomBytes(1024); + zlibB.gzip(expect, function (err, cmpA) { + zlibA.gunzip(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.gzip -> zlibA.gunzip', function (t) { + const expect = 'lololololoollolololoololololololololololololololololololololol'; + zlibB.gzip(expect, function (err, cmpA) { + zlibA.gunzip(cmpA, function (err, result) { + t.same(result.toString(), expect, 'should match'); + t.end(); + }); + }); +}); + diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js new file mode 100644 index 000000000..a9ea566d3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js @@ -0,0 +1,55 @@ +/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */ +(function() {'use strict';function m(c){throw c;}var r=void 0,u=!0;var B="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function aa(c){if("string"===typeof c){var a=c.split(""),b,e;b=0;for(e=a.length;b>>0;c=a}for(var f=1,d=0,g=c.length,h,j=0;0>>0};function I(c,a){this.index="number"===typeof a?a:0;this.n=0;this.buffer=c instanceof(B?Uint8Array:Array)?c:new (B?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&m(Error("invalid index"));this.buffer.length<=this.index&&this.f()}I.prototype.f=function(){var c=this.buffer,a,b=c.length,e=new (B?Uint8Array:Array)(b<<1);if(B)e.set(c);else for(a=0;a>>8&255]<<16|K[c>>>16&255]<<8|K[c>>>24&255])>>32-a:K[c]>>8-a);if(8>a+d)g=g<>a-h-1&1,8===++d&&(d=0,e[f++]=K[g],g=0,f===e.length&&(e=this.f()));e[f]=g;this.buffer=e;this.n=d;this.index=f};I.prototype.finish=function(){var c=this.buffer,a=this.index,b;0Q;++Q){for(var R=Q,ga=R,ha=7,R=R>>>1;R;R>>>=1)ga<<=1,ga|=R&1,--ha;ba[Q]=(ga<>>0}var K=ba;var S={k:function(c,a,b){return S.update(c,0,a,b)},update:function(c,a,b,e){for(var f=S.L,d="number"===typeof b?b:b=0,g="number"===typeof e?e:c.length,a=a^4294967295,d=g&7;d--;++b)a=a>>>8^f[(a^c[b])&255];for(d=g>>3;d--;b+=8)a=a>>>8^f[(a^c[b])&255],a=a>>>8^f[(a^c[b+1])&255],a=a>>>8^f[(a^c[b+2])&255],a=a>>>8^f[(a^c[b+3])&255],a=a>>>8^f[(a^c[b+4])&255],a=a>>>8^f[(a^c[b+5])&255],a=a>>>8^f[(a^c[b+6])&255],a=a>>>8^f[(a^c[b+7])&255];return(a^4294967295)>>>0}},ia=S,ja,ka=[0,1996959894,3993919788,2567524794, +124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304, +3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486, +2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580, +2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221, +2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863, +817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];ja=B?new Uint32Array(ka):ka;ia.L=ja;function na(){};function oa(c){this.buffer=new (B?Uint16Array:Array)(2*c);this.length=0}oa.prototype.getParent=function(c){return 2*((c-2)/4|0)};oa.prototype.push=function(c,a){var b,e,f=this.buffer,d;b=this.length;f[this.length++]=a;for(f[this.length++]=c;0f[e])d=f[b],f[b]=f[e],f[e]=d,d=f[b+1],f[b+1]=f[e+1],f[e+1]=d,b=e;else break;return this.length}; +oa.prototype.pop=function(){var c,a,b=this.buffer,e,f,d;a=b[0];c=b[1];this.length-=2;b[0]=b[this.length];b[1]=b[this.length+1];for(d=0;;){f=2*d+2;if(f>=this.length)break;f+2b[f]&&(f+=2);if(b[f]>b[d])e=b[d],b[d]=b[f],b[f]=e,e=b[d+1],b[d+1]=b[f+1],b[f+1]=e;else break;d=f}return{index:c,value:a,length:this.length}};function T(c){var a=c.length,b=0,e=Number.POSITIVE_INFINITY,f,d,g,h,j,i,q,l,k;for(l=0;lb&&(b=c[l]),c[l]>=1;for(k=i;kU;U++)switch(u){case 143>=U:sa.push([U+48,8]);break;case 255>=U:sa.push([U-144+400,9]);break;case 279>=U:sa.push([U-256+0,7]);break;case 287>=U:sa.push([U-280+192,8]);break;default:m("invalid literal: "+U)} +pa.prototype.h=function(){var c,a,b,e,f=this.input;switch(this.l){case 0:b=0;for(e=f.length;b>>8&255;k[p++]=i&255;k[p++]=i>>>8&255;if(B)k.set(d,p),p+=d.length,k=k.subarray(0,p);else{q=0;for(l=d.length;qz)for(;0z?z:138,H>z-3&&H=H?(L[J++]=17,L[J++]=H-3,O[17]++):(L[J++]=18,L[J++]=H-11,O[18]++),z-=H;else if(L[J++]=M[y],O[M[y]]++,z--,3>z)for(;0z?z:6,H>z-3&&HG;G++)va[G]=la[ca[G]];for(D=19;4=c:return[265,c-11,1];case 14>=c:return[266,c-13,1];case 16>=c:return[267,c-15,1];case 18>=c:return[268,c-17,1];case 22>=c:return[269,c-19,2];case 26>=c:return[270,c-23,2];case 30>=c:return[271,c-27,2];case 34>=c:return[272,c- +31,2];case 42>=c:return[273,c-35,3];case 50>=c:return[274,c-43,3];case 58>=c:return[275,c-51,3];case 66>=c:return[276,c-59,3];case 82>=c:return[277,c-67,4];case 98>=c:return[278,c-83,4];case 114>=c:return[279,c-99,4];case 130>=c:return[280,c-115,4];case 162>=c:return[281,c-131,5];case 194>=c:return[282,c-163,5];case 226>=c:return[283,c-195,5];case 257>=c:return[284,c-227,5];case 258===c:return[285,c-258,0];default:m("invalid length: "+c)}}var Ba=[],Aa,Ca; +for(Aa=3;258>=Aa;Aa++)Ca=za(),Ba[Aa]=Ca[2]<<24|Ca[1]<<16|Ca[0];var Da=B?new Uint32Array(Ba):Ba; +function ta(c,a){function b(a,c){var b=a.N,d=[],e=0,f;f=Da[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(u){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b- +65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>= +b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:m("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,i;h=0;for(i=d.length;h=d;)v[d++]=0;for(d=0;29>=d;)x[d++]=0}v[256]=1;e=0;for(f=a.length;e=f){l&&b(l,-1);d=0;for(g=f-e;ds&&e+sn&&(C=A,n=s);if(258===s)break}q=new xa(n,e-C);l?l.length2*k[n-1]+p[n]&&(k[n]=2*k[n-1]+p[n]),v[n]=Array(k[n]),x[n]=Array(k[n]);for(C=0;Ch[C]?(v[n][s]=E,x[n][s]=l,D+=2): +(v[n][s]=h[C],x[n][s]=C,++C);F[n]=0;1===p[n]&&b(n)}j=t;i=0;for(q=g.length;i>>=1}return a};function Ea(c,a){this.input=c;this.a=new (B?Uint8Array:Array)(32768);this.l=Fa.u;var b={},e;if((a||!(a={}))&&"number"===typeof a.compressionType)this.l=a.compressionType;for(e in a)b[e]=a[e];b.outputBuffer=this.a;this.H=new pa(this.input,b)}var Fa=ra; +Ea.prototype.h=function(){var c,a,b,e,f,d,g,h=0;g=this.a;c=Ga;switch(c){case Ga:a=Math.LOG2E*Math.log(32768)-8;break;default:m(Error("invalid compression method"))}b=a<<4|c;g[h++]=b;switch(c){case Ga:switch(this.l){case Fa.NONE:f=0;break;case Fa.K:f=1;break;case Fa.u:f=2;break;default:m(Error("unsupported compression type"))}break;default:m(Error("invalid compression method"))}e=f<<6|0;g[h++]=e|31-(256*b+e)%31;d=aa(this.input);this.H.b=h;g=this.H.h();h=g.length;B&&(g=new Uint8Array(g.buffer),g.length<= +h+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,h+4));g[h++]=d>>24&255;g[h++]=d>>16&255;g[h++]=d>>8&255;g[h++]=d&255;return g};function Ha(c,a){this.input=c;this.b=this.c=0;this.g={};a&&(a.flags&&(this.g=a.flags),"string"===typeof a.filename&&(this.filename=a.filename),"string"===typeof a.comment&&(this.comment=a.comment),a.deflateOptions&&(this.m=a.deflateOptions));this.m||(this.m={})} +Ha.prototype.h=function(){var c,a,b,e,f,d,g,h,j=new (B?Uint8Array:Array)(32768),i=0,q=this.input,l=this.c,k=this.filename,p=this.comment;j[i++]=31;j[i++]=139;j[i++]=8;c=0;this.g.fname&&(c|=Ia);this.g.fcomment&&(c|=Ja);this.g.fhcrc&&(c|=Ka);j[i++]=c;a=(Date.now?Date.now():+new Date)/1E3|0;j[i++]=a&255;j[i++]=a>>>8&255;j[i++]=a>>>16&255;j[i++]=a>>>24&255;j[i++]=0;j[i++]=Ya;if(this.g.fname!==r){g=0;for(h=k.length;g>>8&255),j[i++]=d&255;j[i++]=0}if(this.g.comment){g= +0;for(h=p.length;g>>8&255),j[i++]=d&255;j[i++]=0}this.g.fhcrc&&(b=S.k(j,0,i)&65535,j[i++]=b&255,j[i++]=b>>>8&255);this.m.outputBuffer=j;this.m.outputIndex=i;f=new pa(q,this.m);j=f.h();i=f.b;B&&(i+8>j.buffer.byteLength?(this.a=new Uint8Array(i+8),this.a.set(new Uint8Array(j.buffer)),j=this.a):j=new Uint8Array(j.buffer));e=S.k(q);j[i++]=e&255;j[i++]=e>>>8&255;j[i++]=e>>>16&255;j[i++]=e>>>24&255;h=q.length;j[i++]=h&255;j[i++]=h>>>8&255;j[i++]=h>>>16&255;j[i++]= +h>>>24&255;this.c=l;B&&i>>=1;switch(c){case 0:var a=this.input,b=this.c,e=this.a,f=this.b,d=r,g=r,h=r,j=e.length,i=r;this.e=this.j=0;d=a[b++];d===r&&m(Error("invalid uncompressed block header: LEN (first byte)"));g=d;d=a[b++];d===r&&m(Error("invalid uncompressed block header: LEN (second byte)"));g|=d<<8;d=a[b++];d===r&&m(Error("invalid uncompressed block header: NLEN (first byte)"));h=d;d=a[b++];d===r&&m(Error("invalid uncompressed block header: NLEN (second byte)"));h|= +d<<8;g===~h&&m(Error("invalid uncompressed block header: length verify"));b+g>a.length&&m(Error("input buffer is broken"));switch(this.r){case $a:for(;f+g>e.length;){i=j-f;g-=i;if(B)e.set(a.subarray(b,b+i),f),f+=i,b+=i;else for(;i--;)e[f++]=a[b++];this.b=f;e=this.f();f=this.b}break;case Za:for(;f+g>e.length;)e=this.f({B:2});break;default:m(Error("invalid inflate mode"))}if(B)e.set(a.subarray(b,b+g),f),f+=g,b+=g;else for(;g--;)e[f++]=a[b++];this.c=b;this.b=f;this.a=e;break;case 1:this.s(ab,bb);break; +case 2:cb(this);break;default:m(Error("unknown BTYPE: "+c))}}return this.z()}; +var db=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],eb=B?new Uint16Array(db):db,fb=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],gb=B?new Uint16Array(fb):fb,hb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],ib=B?new Uint8Array(hb):hb,jb=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],kb=B?new Uint16Array(jb):jb,lb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10, +10,11,11,12,12,13,13],mb=B?new Uint8Array(lb):lb,nb=new (B?Uint8Array:Array)(288),Y,ob;Y=0;for(ob=nb.length;Y=Y?8:255>=Y?9:279>=Y?7:8;var ab=T(nb),pb=new (B?Uint8Array:Array)(30),qb,rb;qb=0;for(rb=pb.length;qb>>a;c.e=e-a;c.c=d;return g} +function sb(c,a){for(var b=c.j,e=c.e,f=c.input,d=c.c,g=a[0],h=a[1],j,i,q;e>>16;c.j=b>>q;c.e=e-q;c.c=d;return i&65535} +function cb(c){function a(a,b,c){var d,f,e,g;for(g=0;gd)e>=f&&(this.b=e,b=this.f(),e=this.b),b[e++]=d;else{g=d-257;j=gb[g];0=f&&(this.b=e,b=this.f(),e=this.b);for(;j--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e}; +W.prototype.Q=function(c,a){var b=this.a,e=this.b;this.A=c;for(var f=b.length,d,g,h,j;256!==(d=sb(this,c));)if(256>d)e>=f&&(b=this.f(),f=b.length),b[e++]=d;else{g=d-257;j=gb[g];0f&&(b=this.f(),f=b.length);for(;j--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e}; +W.prototype.f=function(){var c=new (B?Uint8Array:Array)(this.b-32768),a=this.b-32768,b,e,f=this.a;if(B)c.set(f.subarray(32768,c.length));else{b=0;for(e=c.length;bb;++b)f[b]=f[a+b];this.b=32768;return f}; +W.prototype.R=function(c){var a,b=this.input.length/this.c+1|0,e,f,d,g=this.input,h=this.a;c&&("number"===typeof c.B&&(b=c.B),"number"===typeof c.M&&(b+=c.M));2>b?(e=(g.length-this.c)/this.A[2],d=258*(e/2)|0,f=da&&(this.a.length=a),c=this.a);return this.buffer=c};function tb(c){this.input=c;this.c=0;this.member=[]} +tb.prototype.i=function(){for(var c=this.input.length;this.c>>0;S.k(f)!==q&&m(Error("invalid CRC-32 checksum: 0x"+S.k(f).toString(16)+" / 0x"+q.toString(16))); +a.Y=b=(l[k++]|l[k++]<<8|l[k++]<<16|l[k++]<<24)>>>0;(f.length&4294967295)!==b&&m(Error("invalid input size: "+(f.length&4294967295)+" / "+b));this.member.push(a);this.c=k}var p=this.member,t,v,x=0,F=0,w;t=0;for(v=p.length;t>>0,b!==aa(a)&&m(Error("invalid adler-32 checksum")));return a};exports.deflate=vb;exports.deflateSync=wb;exports.inflate=xb;exports.inflateSync=yb;exports.gzip=zb;exports.gzipSync=Ab;exports.gunzip=Bb;exports.gunzipSync=Cb;function vb(c,a,b){process.nextTick(function(){var e,f;try{f=wb(c,b)}catch(d){e=d}a(e,f)})}function wb(c,a){var b;b=(new Ea(c)).h();a||(a={});return a.G?b:Db(b)}function xb(c,a,b){process.nextTick(function(){var e,f;try{f=yb(c,b)}catch(d){e=d}a(e,f)})} +function yb(c,a){var b;c.subarray=c.slice;b=(new ub(c)).i();a||(a={});return a.noBuffer?b:Db(b)}function zb(c,a,b){process.nextTick(function(){var e,f;try{f=Ab(c,b)}catch(d){e=d}a(e,f)})}function Ab(c,a){var b;c.subarray=c.slice;b=(new Ha(c)).h();a||(a={});return a.G?b:Db(b)}function Bb(c,a,b){process.nextTick(function(){var e,f;try{f=Cb(c,b)}catch(d){e=d}a(e,f)})}function Cb(c,a){var b;c.subarray=c.slice;b=(new tb(c)).i();a||(a={});return a.G?b:Db(b)} +function Db(c){var a=new Buffer(c.length),b,e;b=0;for(e=c.length;b=$?8:255>=$?9:279>=$?7:8;T(Jb);var Lb=new (B?Uint8Array:Array)(30),Mb,Nb;Mb=0;for(Nb=Lb.length;Mb= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-nodeunit": "~0.1.2", + "grunt": "~0.4.0" + }, + "main": "lib/contrib", + "dependencies": { + "zlib-browserify": "0.0.1" + }, + "contributors": [ + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com/" + }, + { + "name": "Chris Talkington", + "url": "http://christalkington.com/" + }, + { + "name": "Larry Davis", + "url": "http://lazd.net/" + }, + { + "name": "Sindre Sorhus", + "url": "http://sindresorhus.com" + } + ], + "readme": "# grunt-lib-contrib [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-lib-contrib.png?branch=master)](http://travis-ci.org/gruntjs/grunt-lib-contrib)\n\n> Common functionality shared across grunt-contrib tasks.\n\nThe purpose of grunt-lib-contrib is to explore solutions to common problems task writers encounter, and to ease the upgrade path for contrib tasks.\n\n**These APIs should be considered highly unstable. Depend on them at your own risk!**\n\n_Over time, some of the functionality provided here may be incorporated directly into grunt for mainstream use. Until then, you may require `grunt-lib-contrib` as a dependency in your projects, but be very careful to specify an exact version number instead of a range, as backwards-incompatible changes are likely to be introduced._\n\n### Helper Functions\n\n#### getNamespaceDeclaration(ns)\n\nThis helper is used to build JS namespace declarations.\n\n#### optsToArgs(options)\n\nConvert an object to an array of CLI arguments, which can be used with `child_process.spawn()`.\n\n```js\n// Example\n{\n fooBar: 'a', // ['--foo-bar', 'a']\n fooBar: 1, // ['--foo-bar', '1']\n fooBar: true, // ['--foo-bar']\n fooBar: false, //\n fooBar: ['a', 'b'] // ['--foo-bar', 'a', '--foo-bar', 'b']\n}\n```\n\n#### stripPath(pth, strip)\n\nStrip a path from a path. normalize both paths for best results.\n\n#### minMaxInfo(min, max, report)\n\nHelper for logging compressed, uncompressed and gzipped sizes of strings.\n\n#### report\nChoices: `false`, `'min'`, `'gzip'`\nDefault: `false`\n\nEither do not report anything, report only minification result, or report minification and gzip results.\n\n**Important** Including `'gzip'` results can make this task 5-10x slower depending on the size of the file.\n\n\n```js\nvar max = grunt.file.read('max.js');\nvar min = minify(max);\nminMaxInfo(min, max, 'gzip');\n```\n\nWould print:\n\n```\nOriginal: 495 bytes.\nMinified: 396 bytes.\nGzipped: 36 bytes.\n```\n\n--\n\n*Lib submitted by [Tyler Kellen](https://goingslowly.com/).*", + "readmeFilename": "README.md", + "_id": "grunt-lib-contrib@0.6.1", + "dist": { + "shasum": "42925d314e0307f033f8b65c60d9c4cc595723cb" + }, + "_from": "grunt-lib-contrib@~0.6.1", + "_resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/test/lib_test.js b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/test/lib_test.js new file mode 100644 index 000000000..446864af2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/grunt-lib-contrib/test/lib_test.js @@ -0,0 +1,233 @@ +var grunt = require('grunt'); +var helper = require('../lib/contrib.js').init(grunt); + +exports.lib = { + getNamespaceDeclaration: function(test) { + 'use strict'; + + test.expect(10); + + // Both test should result in this[JST] + var expected = { + namespace: 'this["JST"]', + declaration: 'this["JST"] = this["JST"] || {};' + }; + + var actual = helper.getNamespaceDeclaration("this.JST"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + actual = helper.getNamespaceDeclaration("JST"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + // Templates should be declared globally if this provided + expected = { + namespace: "this", + declaration: "" + }; + + actual = helper.getNamespaceDeclaration("this"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + // Nested namespace declaration + expected = { + namespace: 'this["GUI"]["Templates"]["Main"]', + declaration: 'this["GUI"] = this["GUI"] || {};\n' + + 'this["GUI"]["Templates"] = this["GUI"]["Templates"] || {};\n' + + 'this["GUI"]["Templates"]["Main"] = this["GUI"]["Templates"]["Main"] || {};' + }; + + actual = helper.getNamespaceDeclaration("GUI.Templates.Main"); + test.equal(expected.namespace, actual.namespace, 'namespace incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration incorrect'); + + // Namespace that contains square brackets + expected = { + namespace: 'this["main"]["[test]"]["[test2]"]', + declaration: 'this["main"] = this["main"] || {};\n' + + 'this["main"]["[test]"] = this["main"]["[test]"] || {};\n' + + 'this["main"]["[test]"]["[test2]"] = this["main"]["[test]"]["[test2]"] || {};' + }; + + actual = helper.getNamespaceDeclaration("main.[test].[test2]"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + test.done(); + }, + optsToArgs: function(test) { + 'use strict'; + + test.expect(1); + + var fixture = { + key: 'a', + key2: 1, + key3: true, + key4: false, + key5: ['a', 'b'] + }; + var expected = ['--key', 'a', '--key2', '1', '--key3', '--key5', 'a', '--key5', 'b' ].toString(); + var actual = helper.optsToArgs(fixture).toString(); + test.equal(expected, actual, 'should convert object to array of CLI arguments'); + + test.done(); + }, + stripPath: function(test) { + 'use strict'; + var path = require('path'); + + test.expect(4); + + var actual = helper.stripPath('path1/path2', 'path1'); + var expected = 'path2'; + test.equal(expected, actual, 'should strip path from a directory path and trim it.'); + + actual = helper.stripPath('path1/path2/path3/path4', 'path1/path2'); + expected = path.normalize('path3/path4'); + test.equal(expected, actual, 'should strip path from a directory path and trim it. (deep)'); + + actual = helper.stripPath('path1/file.ext', 'path1'); + expected = 'file.ext'; + test.equal(expected, actual, 'should strip path from a file path and trim it.'); + + actual = helper.stripPath('path1/path2/path3/path4/file.ext', 'path1/path2'); + expected = path.normalize('path3/path4/file.ext'); + test.equal(expected, actual, 'should strip path from a file path and trim it. (deep)'); + + test.done(); + }, + minMaxInfo: function(test) { + 'use strict'; + test.expect(3); + + var max = new Array(100).join('blah '); + var min = max.replace(/\s+/g, ''); + + var actual; + var expected; + + grunt.util.hooker.hook(grunt.log, 'writeln', { + pre: function(result) { + actual += grunt.log.uncolor(result) + grunt.util.linefeed; + return grunt.util.hooker.preempt(); + } + }); + + grunt.util.hooker.hook(grunt.log, 'write', { + pre: function(result) { + actual += grunt.log.uncolor(result); + return grunt.util.hooker.preempt(); + } + }); + + + // No reporting option + actual = ''; + expected = ''; + + helper.minMaxInfo(min, max); + test.equal(expected, actual, 'should not have reported min and max info.'); + + // Report minification results + actual = ''; + expected = [ + 'Original: 495 bytes.', + 'Minified: 396 bytes.' + ].join(grunt.util.linefeed) + grunt.util.linefeed; + + helper.minMaxInfo(min, max, 'min'); + test.equal(expected, actual, 'should have logged min and max info.'); + + // Report minification and gzip results + actual = ''; + expected = [ + 'Original: 495 bytes.', + 'Minified: 396 bytes.', + 'Gzipped: 36 bytes.' + ].join(grunt.util.linefeed) + grunt.util.linefeed; + + helper.minMaxInfo(min, max, 'gzip'); + test.equal(expected, actual, 'should have logged min, max, gzip info.'); + + grunt.util.hooker.unhook(grunt.log, 'writeln'); + grunt.util.hooker.unhook(grunt.log, 'write'); + test.done(); + }, + formatToType: { + amd: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'amd', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to amd with namespace'); + + actual = helper.formatForType(string, 'amd'); + expected = "return function () { }"; + test.equal(expected, actual, 'should format string to amd'); + + test.done(); + }, + commonjs: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'commonjs', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to commonjs with namespace'); + + actual = helper.formatForType(string, 'commonjs'); + expected = "module.exports = function () { }"; + test.equal(expected, actual, 'should format string to commonjs'); + + test.done(); + }, + js: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'js', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to js with namespace'); + + actual = helper.formatForType(string, 'js'); + expected = 'function () { }'; + test.equal(expected, actual, 'should format string to js'); + + test.done(); + }, + html: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'html', 'JST', 'test'); + var expected = 'function () { }'; + test.equal(expected, actual, 'should format string to html with namespace'); + + actual = helper.formatForType(string, 'html'); + expected = 'function () { }'; + test.equal(expected, actual, 'should format string to html'); + + test.done(); + } + } +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-helper.js b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-helper.js new file mode 100644 index 000000000..aa18f2b96 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-helper.js @@ -0,0 +1,31 @@ +/*global jasmine:false, window:false, document:false*/ + +(function(){ + 'use strict'; + + var jasmineEnv = jasmine.getEnv(); + + jasmineEnv.updateInterval = 1000; + var htmlReporter = new jasmine.HtmlReporter(); + jasmineEnv.addReporter(htmlReporter); + + jasmineEnv.specFilter = function(spec) { + return htmlReporter.specFilter(spec); + }; + + var currentWindowOnload = window.onload; + + if (document.readyState !== 'complete') { + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + jasmineEnv.execute(); + }; + } else { + jasmineEnv.execute(); + } + + +}()); + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-html.js b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-html.js new file mode 100644 index 000000000..543d56963 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine-html.js @@ -0,0 +1,681 @@ +jasmine.HtmlReporterHelpers = {}; + +jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { + var results = child.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + + return status; +}; + +jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { + var parentDiv = this.dom.summary; + var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; + var parent = child[parentSuite]; + + if (parent) { + if (typeof this.views.suites[parent.id] == 'undefined') { + this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); + } + parentDiv = this.views.suites[parent.id].element; + } + + parentDiv.appendChild(childElement); +}; + + +jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { + for(var fn in jasmine.HtmlReporterHelpers) { + ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; + } +}; + +jasmine.HtmlReporter = function(_doc) { + var self = this; + var doc = _doc || window.document; + + var reporterView; + + var dom = {}; + + // Jasmine Reporter Public Interface + self.logRunningSpecs = false; + + self.reportRunnerStarting = function(runner) { + var specs = runner.specs() || []; + + if (specs.length == 0) { + return; + } + + createReporterDom(runner.env.versionString()); + doc.body.appendChild(dom.reporter); + setExceptionHandling(); + + reporterView = new jasmine.HtmlReporter.ReporterView(dom); + reporterView.addSpecs(specs, self.specFilter); + }; + + self.reportRunnerResults = function(runner) { + reporterView && reporterView.complete(); + }; + + self.reportSuiteResults = function(suite) { + reporterView.suiteComplete(suite); + }; + + self.reportSpecStarting = function(spec) { + if (self.logRunningSpecs) { + self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } + }; + + self.reportSpecResults = function(spec) { + reporterView.specComplete(spec); + }; + + self.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } + }; + + self.specFilter = function(spec) { + if (!focusedSpecName()) { + return true; + } + + return spec.getFullName().indexOf(focusedSpecName()) === 0; + }; + + return self; + + function focusedSpecName() { + var specName; + + (function memoizeFocusedSpec() { + if (specName) { + return; + } + + var paramMap = []; + var params = jasmine.HtmlReporter.parameters(doc); + + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + specName = paramMap.spec; + })(); + + return specName; + } + + function createReporterDom(version) { + dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, + dom.banner = self.createDom('div', { className: 'banner' }, + self.createDom('span', { className: 'title' }, "Jasmine "), + self.createDom('span', { className: 'version' }, version)), + + dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), + dom.alert = self.createDom('div', {className: 'alert'}, + self.createDom('span', { className: 'exceptions' }, + self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'), + self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))), + dom.results = self.createDom('div', {className: 'results'}, + dom.summary = self.createDom('div', { className: 'summary' }), + dom.details = self.createDom('div', { id: 'details' })) + ); + } + + function noTryCatch() { + return window.location.search.match(/catch=false/); + } + + function searchWithCatch() { + var params = jasmine.HtmlReporter.parameters(window.document); + var removed = false; + var i = 0; + + while (!removed && i < params.length) { + if (params[i].match(/catch=/)) { + params.splice(i, 1); + removed = true; + } + i++; + } + if (jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + + return params.join("&"); + } + + function setExceptionHandling() { + var chxCatch = document.getElementById('no_try_catch'); + + if (noTryCatch()) { + chxCatch.setAttribute('checked', true); + jasmine.CATCH_EXCEPTIONS = false; + } + chxCatch.onclick = function() { + window.location.search = searchWithCatch(); + }; + } +}; +jasmine.HtmlReporter.parameters = function(doc) { + var paramStr = doc.location.search.substring(1); + var params = []; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + } + return params; +} +jasmine.HtmlReporter.sectionLink = function(sectionName) { + var link = '?'; + var params = []; + + if (sectionName) { + params.push('spec=' + encodeURIComponent(sectionName)); + } + if (!jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + if (params.length > 0) { + link += params.join("&"); + } + + return link; +}; +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter); +jasmine.HtmlReporter.ReporterView = function(dom) { + this.startedAt = new Date(); + this.runningSpecCount = 0; + this.completeSpecCount = 0; + this.passedCount = 0; + this.failedCount = 0; + this.skippedCount = 0; + + this.createResultsMenu = function() { + this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, + this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), + ' | ', + this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); + + this.summaryMenuItem.onclick = function() { + dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); + }; + + this.detailsMenuItem.onclick = function() { + showDetails(); + }; + }; + + this.addSpecs = function(specs, specFilter) { + this.totalSpecCount = specs.length; + + this.views = { + specs: {}, + suites: {} + }; + + for (var i = 0; i < specs.length; i++) { + var spec = specs[i]; + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); + if (specFilter(spec)) { + this.runningSpecCount++; + } + } + }; + + this.specComplete = function(spec) { + this.completeSpecCount++; + + if (isUndefined(this.views.specs[spec.id])) { + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); + } + + var specView = this.views.specs[spec.id]; + + switch (specView.status()) { + case 'passed': + this.passedCount++; + break; + + case 'failed': + this.failedCount++; + break; + + case 'skipped': + this.skippedCount++; + break; + } + + specView.refresh(); + this.refresh(); + }; + + this.suiteComplete = function(suite) { + var suiteView = this.views.suites[suite.id]; + if (isUndefined(suiteView)) { + return; + } + suiteView.refresh(); + }; + + this.refresh = function() { + + if (isUndefined(this.resultsMenu)) { + this.createResultsMenu(); + } + + // currently running UI + if (isUndefined(this.runningAlert)) { + this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" }); + dom.alert.appendChild(this.runningAlert); + } + this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); + + // skipped specs UI + if (isUndefined(this.skippedAlert)) { + this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); + } + + this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.skippedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.skippedAlert); + } + + // passing specs UI + if (isUndefined(this.passedAlert)) { + this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); + } + this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); + + // failing specs UI + if (isUndefined(this.failedAlert)) { + this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); + } + this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); + + if (this.failedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.failedAlert); + dom.alert.appendChild(this.resultsMenu); + } + + // summary info + this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); + this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; + }; + + this.complete = function() { + dom.alert.removeChild(this.runningAlert); + + this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.failedCount === 0) { + dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); + } else { + showDetails(); + } + + dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); + }; + + return this; + + function showDetails() { + if (dom.reporter.className.search(/showDetails/) === -1) { + dom.reporter.className += " showDetails"; + } + } + + function isUndefined(obj) { + return typeof obj === 'undefined'; + } + + function isDefined(obj) { + return !isUndefined(obj); + } + + function specPluralizedFor(count) { + var str = count + " spec"; + if (count > 1) { + str += "s" + } + return str; + } + +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); + + +jasmine.HtmlReporter.SpecView = function(spec, dom, views) { + this.spec = spec; + this.dom = dom; + this.views = views; + + this.symbol = this.createDom('li', { className: 'pending' }); + this.dom.symbolSummary.appendChild(this.symbol); + + this.summary = this.createDom('div', { className: 'specSummary' }, + this.createDom('a', { + className: 'description', + href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.description) + ); + + this.detail = this.createDom('div', { className: 'specDetail' }, + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.getFullName()) + ); +}; + +jasmine.HtmlReporter.SpecView.prototype.status = function() { + return this.getSpecStatus(this.spec); +}; + +jasmine.HtmlReporter.SpecView.prototype.refresh = function() { + this.symbol.className = this.status(); + + switch (this.status()) { + case 'skipped': + break; + + case 'passed': + this.appendSummaryToSuiteDiv(); + break; + + case 'failed': + this.appendSummaryToSuiteDiv(); + this.appendFailureDetail(); + break; + } +}; + +jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { + this.summary.className += ' ' + this.status(); + this.appendToSummary(this.spec, this.summary); +}; + +jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { + this.detail.className += ' ' + this.status(); + + var resultItems = this.spec.results().getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + this.detail.appendChild(messagesDiv); + this.dom.details.appendChild(this.detail); + } +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { + this.suite = suite; + this.dom = dom; + this.views = views; + + this.element = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) + ); + + this.appendToSummary(this.suite, this.element); +}; + +jasmine.HtmlReporter.SuiteView.prototype.status = function() { + return this.getSpecStatus(this.suite); +}; + +jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { + this.element.className += " " + this.status(); +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); + +/* @deprecated Use jasmine.HtmlReporter instead + */ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.css b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.css new file mode 100644 index 000000000..8c008dc72 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.css @@ -0,0 +1,82 @@ +body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } + +#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +#HTMLReporter a { text-decoration: none; } +#HTMLReporter a:hover { text-decoration: underline; } +#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } +#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } +#HTMLReporter #jasmine_content { position: fixed; right: 100%; } +#HTMLReporter .version { color: #aaaaaa; } +#HTMLReporter .banner { margin-top: 14px; } +#HTMLReporter .duration { color: #aaaaaa; float: right; } +#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } +#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } +#HTMLReporter .symbolSummary li.passed { font-size: 14px; } +#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } +#HTMLReporter .symbolSummary li.failed { line-height: 9px; } +#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } +#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } +#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } +#HTMLReporter .symbolSummary li.pending { line-height: 11px; } +#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } +#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +#HTMLReporter .runningAlert { background-color: #666666; } +#HTMLReporter .skippedAlert { background-color: #aaaaaa; } +#HTMLReporter .skippedAlert:first-child { background-color: #333333; } +#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } +#HTMLReporter .passingAlert { background-color: #a6b779; } +#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } +#HTMLReporter .failingAlert { background-color: #cf867e; } +#HTMLReporter .failingAlert:first-child { background-color: #b03911; } +#HTMLReporter .results { margin-top: 14px; } +#HTMLReporter #details { display: none; } +#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } +#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter.showDetails .summary { display: none; } +#HTMLReporter.showDetails #details { display: block; } +#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter .summary { margin-top: 14px; } +#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } +#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } +#HTMLReporter .summary .specSummary.failed a { color: #b03911; } +#HTMLReporter .description + .suite { margin-top: 0; } +#HTMLReporter .suite { margin-top: 14px; } +#HTMLReporter .suite a { color: #333333; } +#HTMLReporter #details .specDetail { margin-bottom: 28px; } +#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } +#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } +#HTMLReporter .resultMessage span.result { display: block; } +#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } + +#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } +#TrivialReporter a:visited, #TrivialReporter a { color: #303; } +#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } +#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } +#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } +#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } +#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } +#TrivialReporter .runner.running { background-color: yellow; } +#TrivialReporter .options { text-align: right; font-size: .8em; } +#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } +#TrivialReporter .suite .suite { margin: 5px; } +#TrivialReporter .suite.passed { background-color: #dfd; } +#TrivialReporter .suite.failed { background-color: #fdd; } +#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } +#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } +#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } +#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } +#TrivialReporter .spec.skipped { background-color: #bbb; } +#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } +#TrivialReporter .passed { background-color: #cfc; display: none; } +#TrivialReporter .failed { background-color: #fbb; } +#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } +#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } +#TrivialReporter .resultMessage .mismatch { color: black; } +#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } +#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } +#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } +#TrivialReporter #jasmine_content { position: fixed; right: 100%; } +#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.js b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.js new file mode 100644 index 000000000..6b3459b91 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/jasmine.js @@ -0,0 +1,2600 @@ +var isCommonJS = typeof window == "undefined" && typeof exports == "object"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Maximum levels of nesting that will be included when an object is pretty-printed + */ +jasmine.MAX_PRETTY_PRINT_DEPTH = 40; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +/** + * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite. + * Set to false to let the exception bubble up in the browser. + * + */ +jasmine.CATCH_EXCEPTIONS = true; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + * @return {jasmine.Matchers} + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.source != b.source) + mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/"); + + if (a.ignoreCase != b.ignoreCase) + mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.global != b.global) + mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.multiline != b.multiline) + mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.sticky != b.sticky) + mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier"); + + return (mismatchValues.length === 0); +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a.jasmineMatches) { + return a.jasmineMatches(b); + } + + if (b.jasmineMatches) { + return b.jasmineMatches(a); + } + + if (a instanceof jasmine.Matchers.ObjectContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.ObjectContaining) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (a instanceof RegExp && b instanceof RegExp) { + return this.compareRegExps_(a, b, mismatchKeys, mismatchValues); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + if (!jasmine.CATCH_EXCEPTIONS) { + this.func.apply(this.spec); + } + else { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that compares the actual to NaN. + */ +jasmine.Matchers.prototype.toBeNaN = function() { + this.message = function() { + return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ]; + }; + + return (this.actual !== this.actual); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."; + var positiveMessage = ""; + if (this.actual.callCount === 0) { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; + } else { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '') + } + return [positiveMessage, invertedMessage]; + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision, as number of decimal places + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2); +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} [expected] + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineToString = function() { + return ''; +}; + +jasmine.Matchers.ObjectContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { + return ""; +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!obj.hasOwnProperty(property)) continue; + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Array"); + return; + } + + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Object"); + return; + } + + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + + // parallel to blocks. each true value in this array means the block will + // get executed even if we abort + this.ensured = []; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.unshift(block); + this.ensured.unshift(ensure); +}; + +jasmine.Queue.prototype.add = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.push(block); + this.ensured.push(ensure); +}; + +jasmine.Queue.prototype.insertNext = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.ensured.splice((this.index + this.offset + 1), 0, ensure); + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this), true); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 3, + "build": 1, + "revision": 1354556913 +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/phantom-polyfill.js b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/phantom-polyfill.js new file mode 100644 index 000000000..80a9f739d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/phantom-polyfill.js @@ -0,0 +1,24 @@ + + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind + +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + FNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + FNOP.prototype = this.prototype; + fBound.prototype = new FNOP(); + + return fBound; + }; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/reporter.js b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/reporter.js new file mode 100644 index 000000000..5a400afe0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.grunt/grunt-contrib-jasmine/reporter.js @@ -0,0 +1,287 @@ +/*global window:false, alert:false, jasmine:false, Node:false, */ +/*jshint curly:false*/ + +'use strict'; + +var phantom = {}; + +if (window._phantom) { + console.log = function(){ + phantom.sendMessage('verbose',Array.prototype.slice.apply(arguments).join(', ')); + }; +} + +phantom.sendMessage = function() { + var args = [].slice.call( arguments ); + var payload = JSON.stringify( args ); + if (window._phantom) { + // alerts are the communication bridge to grunt + alert( payload ); + } +}; + +(function(){ + + function PhantomReporter() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; + this.buffer = ''; + } + + PhantomReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } + phantom.sendMessage('jasmine.reportRunnerStarting', this.suites_); + }; + + PhantomReporter.prototype.reportSpecStarting = function(spec) { + spec.startTime = (new Date()).getTime(); + var message = { + suite : { + description : spec.suite.description + }, + description : spec.description + }; + phantom.sendMessage('jasmine.reportSpecStarting', message); + }; + + PhantomReporter.prototype.suites = function() { + return this.suites_; + }; + + PhantomReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; + }; + + PhantomReporter.prototype.results = function() { + return this.results_; + }; + + PhantomReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; + }; + + function map(values, f) { + var result = []; + for (var ii = 0; ii < values.length; ii++) { + result.push(f(values[ii])); + } + return result; + } + + PhantomReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; + var specIds = map(runner.specs(), function(a){return a.id;}); + var summary = this.resultsForSpecs(specIds); + phantom.sendMessage('jasmine.reportRunnerResults',summary); + phantom.sendMessage('jasmine.reportJUnitResults', this.generateJUnitSummary(runner)); + phantom.sendMessage('jasmine.done.PhantomReporter'); + }; + + PhantomReporter.prototype.reportSuiteResults = function(suite) { + if (suite.specs().length) { + suite.timestamp = new Date(); + suite.duration = suite.timestamp.getTime() - suite.specs()[0].startTime; + phantom.sendMessage('jasmine.reportSuiteResults',{ + description : suite.description, + results : suite.results() + }); + } + }; + + function stringify(obj) { + if (typeof obj !== 'object') return obj; + + var cache = [], keyMap = [], index; + + var string = JSON.stringify(obj, function(key, value) { + // Let json stringify falsy values + if (!value) return value; + + // If we're a node + if (typeof(Node) !== 'undefined' && value instanceof Node) return '[ Node ]'; + + // jasmine-given has expectations on Specs. We intercept to return a + // String to avoid stringifying the entire Jasmine environment, which + // results in exponential string growth + if (value instanceof jasmine.Spec) return '[ Spec: ' + value.description + ' ]'; + + // If we're a window (logic stolen from jQuery) + if (value.window && value.window === value.window.window) return '[ Window ]'; + + // Simple function reporting + if (typeof value === 'function') return '[ Function ]'; + + if (typeof value === 'object' && value !== null) { + + if (index = cache.indexOf(value) !== -1) { + // If we have it in cache, report the circle with the key we first found it in + return '[ Circular {' + (keyMap[index] || 'root') + '} ]'; + } + cache.push(value); + keyMap.push(key); + } + return value; + }); + return string; + } + + PhantomReporter.prototype.reportSpecResults = function(spec) { + spec.duration = (new Date()).getTime() - spec.startTime; + var _results = spec.results(); + var results = { + description : _results.description, + messages : _results.getItems(), + failedCount : _results.failedCount, + totalCount : _results.totalCount, + passedCount : _results.passedCount, + skipped : _results.skipped, + passed : _results.passed(), + msg : _results.failedCount > 0 ? "failed" : "passed" + }; + this.results_[spec.id] = results; + + // Quick hack to alleviate cyclical object breaking JSONification. + for (var ii = 0; ii < results.messages.length; ii++) { + var item = results.messages[ii]; + if (item.expected) { + item.expected = stringify(item.expected); + } + if (item.actual) { + item.actual = stringify(item.actual); + } + } + + phantom.sendMessage( 'jasmine.reportSpecResults', spec.id, results, this.getFullName(spec)); + }; + + PhantomReporter.prototype.getFullName = function(spec) { + return getNestedSuiteName(spec.suite, ':: ') + ':: ' + spec.description; + }; + + PhantomReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; + }; + + PhantomReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type === 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; + }; + + function getNestedSuiteName(suite, sep) { + var names = []; + while (suite) { + names.unshift(suite.description); + suite = suite.parentSuite; + } + return names.join(sep ? sep : ' '); + } + + function getTopLevelSuiteId(suite) { + var id; + while (suite) { + id = suite.id; + suite = suite.parentSuite; + } + return id; + } + + PhantomReporter.prototype.generateJUnitSummary = function(runner) { + var consolidatedSuites = {}, + suites = map(runner.suites(), function(suite) { + var failures = 0; + + var testcases = map(suite.specs(), function(spec) { + var failureMessages = []; + var specResults = spec.results(); + var resultsItems = specResults.items_; + var resultsItemCount = resultsItems.length; + + if (specResults.failedCount) { + failures++; + + for (var ii = 0; ii < resultsItemCount; ii++) { + var expectation = resultsItems[ii]; + if (!expectation.passed()) { + failureMessages.push(expectation.message); + } + } + } + return { + assertions: resultsItemCount, + className: getNestedSuiteName(spec.suite), + name: spec.description, + time: spec.duration / 1000, + failureMessages: failureMessages + }; + }); + + var data = { + name: getNestedSuiteName(suite), + time: suite.duration / 1000, + timestamp: suite.timestamp, + tests: suite.specs().length, + errors: 0, // TODO: These exist in the JUnit XML but not sure how they map to jasmine things + testcases: testcases, + failures: failures + }; + + if (suite.parentSuite) { + consolidatedSuites[getTopLevelSuiteId(suite)].push(data); + } else { + consolidatedSuites[suite.id] = [data]; + } + return data; + }); + + return { + suites: suites, + consolidatedSuites: consolidatedSuites + }; + }; + + jasmine.getEnv().addReporter( new PhantomReporter() ); +}()); diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/.name b/node_modules/grunt-contrib-less/node_modules/less/.idea/.name new file mode 100644 index 000000000..de7c7ff94 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/.name @@ -0,0 +1 @@ +less.js \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/encodings.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/encodings.xml new file mode 100644 index 000000000..7c62b52a1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/Project_Default.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..4fc54f57c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/profiles_settings.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..6933c1eaf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLibraryMappings.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLibraryMappings.xml new file mode 100644 index 000000000..57022611f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLibraryMappings.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLinters/jshint.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLinters/jshint.xml new file mode 100644 index 000000000..2b7f8e2ad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/jsLinters/jshint.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/less.js.iml b/node_modules/grunt-contrib-less/node_modules/less/.idea/less.js.iml new file mode 100644 index 000000000..c0126df53 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/less.js.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/libraries/sass_stdlib.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/libraries/sass_stdlib.xml new file mode 100644 index 000000000..8962a7d07 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/libraries/sass_stdlib.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/misc.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/misc.xml new file mode 100644 index 000000000..262e5d32b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/modules.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/modules.xml new file mode 100644 index 000000000..d74aefb71 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/scopes/scope_settings.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/scopes/scope_settings.xml new file mode 100644 index 000000000..0d5175ca0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/vcs.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/vcs.xml new file mode 100644 index 000000000..ab55cf163 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.idea/workspace.xml b/node_modules/grunt-contrib-less/node_modules/less/.idea/workspace.xml new file mode 100644 index 000000000..83e0a5c3d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.idea/workspace.xml @@ -0,0 +1,622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1357400236487 + 1357400236487 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/.jshintrc b/node_modules/grunt-contrib-less/node_modules/less/.jshintrc new file mode 100644 index 000000000..0d5dbf2ab --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.jshintrc @@ -0,0 +1,11 @@ +{ + "evil": true, + "boss": true, + "expr": true, + "laxbreak": true, + "latedef": true, + "node": true, + "undef": true, + "unused": "vars", + "noarg": true +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/.npmignore new file mode 100644 index 000000000..bc8ad3f73 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/.npmignore @@ -0,0 +1 @@ +.gitattributes diff --git a/node_modules/grunt-contrib-less/node_modules/less/CHANGELOG.md b/node_modules/grunt-contrib-less/node_modules/less/CHANGELOG.md new file mode 100644 index 000000000..10025733d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/CHANGELOG.md @@ -0,0 +1,224 @@ +# 1.5.1 + +2013-11-17 + + - Added source-map-URL option + - Fixed a bug which meant the minimised 1.5.0 browser version was not wrapped, meaning it interfered with require js + - Fixed a bug where the browser version assume port was specified + - Added the ability to specify variables on the command line + - Upgraded clean-css and fixed it from trying to import + - correct a bug meaning imports weren't synchronous (syncImport option available for full synchronous behaviour) + - better mixin matching behaviour with calling multiple classes e.g. .a.b.c; + +# 1.5.0 + +2013-10-21 + + - sourcemap support + - support for import inline option to include css that you do NOT want less to parse e.g. `@import (inline) "file.css";` + - better support for modifyVars (refresh styles with new variables, using a file cache), is now more resiliant + - support for import reference option to reference external css, but not output it. Any mixin calls or extend's will be output. + - support for guards on selectors (currently only if you have a single selector) + - allow property merging through the +: syntax + - Added min/max functions + - Added length function and improved extract to work with comma seperated values + - when using import multiple, sub imports are imported multiple times into final output + - fix bad spaces between namespace operators + - do not compress comment if it begins with an exclamation mark + - Fix the saturate function to pass through when using the CSS syntax + - Added svg-gradient function + - Added no-js option to lessc (in browser, use javascriptEnabled: false) which disallows JavaScript in less files + - switched from the little supported and buggy cssmin (previously ycssmin) to clean-css + - support transparent as a color, but not convert between rgba(0, 0, 0, 0) and transparent + - remove sys.puts calls to stop deprecation warnings in future node.js releases + - Browser: added logLevel option to control logging (2 = everything, 1 = errors only, 0 = no logging) + - Browser: added errorReporting option which can be "html" (default) or "console" or a function + - Now uses grunt for building and testing + - A few bug fixes for media queries, extends, scoping, compression and import once. + +# 1.4.2 + +2013-07-20 + + - if you don't pass a strict maths option, font size/line height options are output correctly again + - npmignore now include .gitattributes + - property names may include capital letters + - various windows path fixes (capital letters, multiple // in a path) + +# 1.4.1 + +2013-07-05 + + - fix syncImports and yui-compress option, as they were being ignored + - fixed several global variable leaks + - handle getting null or undefined passed as the options object + +# 1.4.0 + +2013-06-05 + + - fix passing of strict maths option + +# 1.4.0 Beta 4 + +2013-05-04 + + - change strictMaths to strictMath. Enable this with --strict-math=on in lessc and strictMath:true in JavaScript. + - change lessc option for strict units to --strict-units=off + +# 1.4.0 Beta 3 + +2013-04-30 + + - strictUnits now defaults to false and the true case now gives more useful but less correct results, e.g. 2px/1px = 2px + - Process ./ when having relative paths + - add isunit function for mixin guards and non basic units + - extends recognise attributes + - exception errors extend the JavaScript Error + - remove es-5-shim as standard from the browser + - Fix path issues with windows/linux local paths + +# 1.4.0 Beta 1 & 2 + +2013-03-07 + + - support for `:extend()` in selectors (e.g. `input:extend(.button) {}`) and `&:extend();` in ruleset (e.g. `input { &:extend(.button all); }`) + - maths is now only done inside brackets. This means font: statements, media queries and the calc function can use a simpler format without being escaped. Disable this with --strict-maths-off in lessc and strictMaths:false in JavaScript. + - units are calculated, e.g. 200cm+1m = 3m, 3px/1px = 3. If you use units inconsistently you will get an error. Suppress this error with --strict-units-off in lessc or strictUnits:false in JavaScript + - `(~"@var")` selector interpolation is removed. Use @{var} in selectors to have variable selectors + - default behaviour of import is to import each file once. `@import-once` has been removed. + - You can specify options on imports to force it to behave as css or less `@import (less) "file.css"` will process the file as less + - variables in mixins no longer 'leak' into their calling scope + - added data-uri function which will inline an image into the output css. If ieCompat option is true and file is too large, it will fallback to a url() + - significant bug fixes to our debug options + - other parameters can be used as defaults in mixins e.g. .a(@a, @b:@a) + - an error is shown if properties are used outside of a ruleset + - added extract function which picks a value out of a list, e.g. extract(12 13 14, 3) => 14 + - added luma, hsvhue, hsvsaturation, hsvvalue functions + - added pow, pi, mod, tan, sin, cos, atan, asin, acos and sqrt math functions + - added convert function, e.g. convert(1rad, deg) => value in degrees + - lessc makes output directories if they don't exist + - lessc `@import` supports https and 301's + - lessc "-depends" option for lessc writes out the list of import files used in makefile format + - lessc "-lint" option just reports errors + - support for namespaces in attributes and selector interpolation in attributes + - other bug fixes + +# 1.3.3 + +2012-12-30 + + - Fix critical bug with mixin call if using multiple brackets + - when using the filter contrast function, the function is passed through if the first argument is not a color + +# 1.3.2 + +2012-12-28 + + - browser and server url re-writing is now aligned to not re-write (previous lessc behaviour) + - url-rewriting can be made to re-write to be relative to the entry file using the relative-urls option (less.relativeUrls option) + - rootpath option can be used to add a base path to every url + - Support mixin argument seperator of ';' so you can pass comma seperated values. e.g. `.mixin(23px, 12px;);` + - Fix lots of problems with named arguments in corner cases, not behaving as expected + - hsv, hsva, unit functions + - fixed lots more bad error messages + - fix `@import-once` to use the full path, not the relative one for determining if an import has been imported already + - support `:not(:nth-child(3))` + - mixin guards take units into account + - support unicode descriptors (`U+00A1-00A9`) + - support calling mixins with a stack when using `&` (broken in 1.3.1) + - support `@namespace` and namespace combinators + - when using % with colour functions, take into account a colour is out of 256 + - when doing maths with a % do not divide by 100 and keep the unit + - allow url to contain % (e.g. %20 for a space) + - if a mixin guard stops execution a default mixin is not required + - units are output in strings (use the unit function if you need to get the value without unit) + - do not infinite recurse when mixins call mixins of the same name + - fix issue on important on mixin calls + - fix issue with multiple comments being confused + - tolerate multiple semi-colons on rules + - ignore subsequant `@charset` + - syncImport option for node.js to read files syncronously + - write the output directory if it is missing + - change dependency on cssmin to ycssmin + - lessc can load files over http + - allow calling less.watch() in non dev mode + - don't cache in dev mode + - less files cope with query parameters better + - sass debug statements are now chrome compatible + - modifyVars function added to re-render with different root variables + +# 1.3.1 + +2012-10-18 + +- Support for comment and @media debugging statements +- bug fix for async access in chrome extensions +- new functions tint, shade, multiply, screen, overlay, hardlight, difference, exclusion, average, negation, softlight, red, green, blue, contrast +- allow escaped characters in attributes +- in selectors support @{a} directly, e.g. .a.@{a} { color: black; } +- add fraction parameter to round function +- much better support for & selector +- preserve order of link statements client side +- lessc has better help +- rhino version fixed +- fix bugs in clientside error handling +- support dpi, vmin, vm, dppx, dpcm units +- Fix ratios in media statements +- in mixin guards allow comparing colors and strings +- support for -*-keyframes (for -khtml but now supports any) +- in mix function, default weight to 50% +- support @import-once +- remove duplicate rules in output +- implement named parameters when calling mixins +- many numerous bug fixes + +# 1.3.0 + +2012-03-10 + +- @media bubbling +- Support arbitrary entities as selectors +- [Variadic argument support](https://gist.github.com/1933613) +- Behaviour of zero-arity mixins has [changed](https://gist.github.com/1933613) +- Allow `@import` directives in any selector +- Media-query features can now be a variable +- Automatic merging of media-query conditions +- Fix global variable leaks +- Fix error message on wrong-arity call +- Fix an `@arguments` behaviour bug +- Fix `::` selector output +- Fix a bug when using @media with mixins + + +# 1.2.1 + +2012-01-15 + +- Fix imports in browser +- Improve error reporting in browser +- Fix Runtime error reports from imported files +- Fix `File not found` import error reporting + + +# 1.2.0 + +2012-01-07 + +- Mixin guards +- New function `percentage` +- New `color` function to parse hex color strings +- New type-checking stylesheet functions +- Fix Rhino support +- Fix bug in string arguments to mixin call +- Fix error reporting when index is 0 +- Fix browser support in WebKit and IE +- Fix string interpolation bug when var is empty +- Support `!important` after mixin calls +- Support vanilla @keyframes directive +- Support variables in certain css selectors, like `nth-child` +- Support @media and @import features properly +- Improve @import support with media features +- Improve error reports from imported files +- Improve function call error reporting +- Improve error-reporting diff --git a/node_modules/grunt-contrib-less/node_modules/less/CONTRIBUTING.md b/node_modules/grunt-contrib-less/node_modules/less/CONTRIBUTING.md new file mode 100644 index 000000000..0d89c29a6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# Contributing to Less.js + +> We welcome feature requests and bug reports. Please read these guidelines before submitting one. + + +**Words that begin with the at sign (`@`) must be wrapped in backticks!** . As a courtesy to avoid sending notifications to any user that might have the `@username` being referenced, please remember that GitHub usernames also start with the at sign. If you don't wrap them in backticks, users will get unintended notifications from you. + +GitHub has other great markdown features as well, [go here to learn more about them](https://help.github.com/articles/github-flavored-markdown). + + +## Reporting Issues + +We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Less.js core. Please read the following guidelines before opening any issue. + +1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. +2. **Create an isolated and reproducible test case.** Be sure the problem exists in Less.js's code with [reduced test cases](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report. +3. **Test with the latest version**. We get a lot of issues that could be resolved by updating your version of Less.js. +3. **Include a live example.** Please use [less2css.org](http://less2css.org/) for sharing your isolated test cases. +4. **Share as much information as possible.** Include operating system and version. Describe how you use Less. If you use it in the browser, please include browser and version, and the version of Less.js you're using. Let us know if you're using the command line (`lessc`) or an external tool. And try to include steps to reproduce the bug. + + +## Feature Requests + +* Please search for existing feature requests first to see if something similar already exists. +* Include a clear and specific use-case. We love new ideas, but we do not add language features without a reason. +* Consider whether or not your language feature would be better as a function or implemented in a 3rd-party build system such as [assemble-less](http://github.com/assemble/assemble-less). + + +## Pull Requests + +_Pull requests are encouraged!_ + +* Start by adding a feature request to get feedback and see how your idea is received. +* If your pull request solves an existing issue, but it's different in some way, _please create a new issue_ and make sure to discuss it with the core contributors. Otherwise you risk your hard work being rejected. +* Do not change the **./dist/** folder, we do this when releasing +* _Please add tests_ for your work. Use `make test` to see if they pass node.js tests and `make browser-test` to see the browser ([PhantomJS](http://phantomjs.org/)) tests pass. + + +### Coding Standards + +* Always use spaces, never tabs +* End lines in semi-colons. +* Loosely aim towards jsHint standards + + +## Developing +If you want to take an issue just add a small comment saying you are having a go at something, so we don't get duplication. + +Learn more about [developing Less.js](https://github.com/less/less.js/wiki/Developing-less.js). diff --git a/node_modules/grunt-contrib-less/node_modules/less/Gruntfile.js b/node_modules/grunt-contrib-less/node_modules/less/Gruntfile.js new file mode 100644 index 000000000..17186f2db --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/Gruntfile.js @@ -0,0 +1,273 @@ +'use strict'; + +module.exports = function(grunt) { + + // Report the elapsed execution time of tasks. + require('time-grunt')(grunt); + + // Project configuration. + grunt.initConfig({ + + // Metadata required for build. + build: grunt.file.readYAML('build/build.yml'), + pkg: grunt.file.readJSON('package.json'), + meta: { + license: '<%= _.pluck(pkg.licenses, "type").join(", ") %>', + copyright: 'Copyright (c) 2009-<%= grunt.template.today("yyyy") %>', + banner: + '/*! \n' + + ' * LESS - <%= pkg.description %> v<%= pkg.version %> \n' + + ' * http://lesscss.org \n' + + ' * \n' + + ' * <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> \n' + + ' * Licensed under the <%= meta.license %> License. \n' + + ' * \n' + + ' * @licence \n' + + ' */ \n\n' + }, + + shell: { + options: {stdout: true, failOnError: true}, + test: { + command: 'node test/less-test.js' + }, + benchmark: { + command: 'node benchmark/less-benchmark.js' + }, + "browsertest-server": { + command: 'node node_modules/http-server/bin/http-server . -p 8088' + }, + "sourcemap-test": { + command: [ + 'node bin/lessc --source-map --source-map-inline test/less/import.less test/sourcemaps/import.css', + 'node bin/lessc --source-map --source-map-inline test/less/sourcemaps/basic.less test/sourcemaps/basic.css', + 'node node_modules/http-server/bin/http-server test/sourcemaps -p 8084'].join('&&') + } + }, + concat: { + options: { + stripBanners: 'all', + banner: '<%= meta.banner %>\n\n(function (window, undefined) {', + footer: '\n})(window);' + }, + // Browser versions + browsertest: { + src: ['<%= build.browser %>'], + dest: 'test/browser/less.js' + }, + stable: { + src: ['<%= build.browser %>'], + dest: 'dist/less-<%= pkg.version %>.js' + }, + // Rhino + rhino: { + options: { + banner: '/* LESS.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n', + footer: '' // override task-level footer + }, + src: ['<%= build.rhino %>'], + dest: 'dist/less-rhino-<%= pkg.version %>.js' + }, + // Generate readme + readme: { + // override task-level banner and footer + options: {process: true, banner: '', footer: ''}, + src: ['build/README.md'], + dest: 'README.md' + } + }, + + uglify: { + options: { + banner: '<%= meta.banner %>', + mangle: true + }, + stable: { + src: ['<%= concat.stable.dest %>'], + dest: 'dist/less-<%= pkg.version %>.min.js' + } + }, + + jshint: { + options: {jshintrc: '.jshintrc'}, + files: { + src: [ + 'Gruntfile.js', + 'lib/**/*.js' + ] + } + }, + + connect: { + server: { + options: { + port: 8081 + } + } + }, + + jasmine: { + options: { + // version: '2.0.0-rc2', + keepRunner: true, + host: 'http://localhost:8081/', + vendor: ['test/browser/common.js', 'test/browser/less.js'], + template: 'test/browser/test-runner-template.tmpl' + }, + main: { + // src is used to build list of less files to compile + src: ['test/less/*.less', '!test/less/javascript.less', '!test/less/urls.less'], + options: { + helpers: 'test/browser/runner-main-options.js', + specs: 'test/browser/runner-main-spec.js', + outfile: 'tmp/browser/test-runner-main.html' + } + }, + legacy: { + src: ['test/less/legacy/*.less'], + options: { + helpers: 'test/browser/runner-legacy-options.js', + specs: 'test/browser/runner-legacy-spec.js', + outfile: 'tmp/browser/test-runner-legacy.html' + } + }, + errors: { + src: ['test/less/errors/*.less', '!test/less/errors/javascript-error.less'], + options: { + timeout: 20000, + helpers: 'test/browser/runner-errors-options.js', + specs: 'test/browser/runner-errors-spec.js', + outfile: 'tmp/browser/test-runner-errors.html' + } + }, + noJsErrors: { + src: ['test/less/no-js-errors/*.less'], + options: { + helpers: 'test/browser/runner-no-js-errors-options.js', + specs: 'test/browser/runner-no-js-errors-spec.js', + outfile: 'tmp/browser/test-runner-no-js-errors.html' + } + }, + browser: { + src: ['test/browser/less/*.less'], + options: { + helpers: 'test/browser/runner-browser-options.js', + specs: 'test/browser/runner-browser-spec.js', + outfile: 'tmp/browser/test-runner-browser.html' + } + }, + relativeUrls: { + src: ['test/browser/less/relative-urls/*.less'], + options: { + helpers: 'test/browser/runner-relative-urls-options.js', + specs: 'test/browser/runner-relative-urls-spec.js', + outfile: 'tmp/browser/test-runner-relative-urls.html' + } + }, + rootpath: { + src: ['test/browser/less/rootpath/*.less'], + options: { + helpers: 'test/browser/runner-rootpath-options.js', + specs: 'test/browser/runner-rootpath-spec.js', + outfile: 'tmp/browser/test-runner-rootpath.html' + } + }, + rootpathRelative: { + src: ['test/browser/less/rootpath-relative/*.less'], + options: { + helpers: 'test/browser/runner-rootpath-relative-options.js', + specs: 'test/browser/runner-rootpath-relative-spec.js', + outfile: 'tmp/browser/test-runner-rootpath-relative.html' + } + }, + production: { + src: ['test/browser/less/production/*.less'], + options: { + helpers: 'test/browser/runner-production-options.js', + specs: 'test/browser/runner-production-spec.js', + outfile: 'tmp/browser/test-runner-production.html' + } + }, + modifyVars: { + src: ['test/browser/less/modify-vars/*.less'], + options: { + helpers: 'test/browser/runner-modify-vars-options.js', + specs: 'test/browser/runner-modify-vars-spec.js', + outfile: 'tmp/browser/test-runner-modify-vars.html' + } + }, + globalVars: { + src: ['test/browser/less/global-vars/*.less'], + options: { + helpers: 'test/browser/runner-global-vars-options.js', + specs: 'test/browser/runner-global-vars-spec.js', + outfile: 'tmp/browser/test-runner-global-vars.html' + } + } + }, + + // Clean the version of less built for the tests + clean: { + test: ['test/browser/less.js', 'tmp'], + "sourcemap-test": ['test/sourcemaps/*.css', 'test/sourcemaps/*.map'] + } + }); + + // Load these plugins to provide the necessary tasks + require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); + + // Actually load this plugin's task(s). + grunt.loadTasks('build/tasks'); + + // by default, run tests + grunt.registerTask('default', [ + 'test' + ]); + + // Release + grunt.registerTask('stable', [ + 'concat:stable', + 'uglify:stable' + ]); + + // Run all browser tests + grunt.registerTask('browsertest', [ + 'browser', + 'connect', + 'jasmine' + ]); + + // setup a web server to run the browser tests in a browser rather than phantom + grunt.registerTask('browsertest-server', [ + 'shell:browsertest-server' + ]); + + // Create the browser version of less.js + grunt.registerTask('browser', [ + 'concat:browsertest' + ]); + + // Run all tests + grunt.registerTask('test', [ + 'clean', + 'jshint', + 'shell:test', + 'browsertest' + ]); + + // generate a good test environment for testing sourcemaps + grunt.registerTask('sourcemap-test', [ + 'clean:sourcemap-test', + 'shell:sourcemap-test' + ]); + + // Run benchmark + grunt.registerTask('benchmark', [ + 'shell:benchmark' + ]); + + // Readme. + grunt.registerTask('readme', [ + 'concat:readme' + ]); +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/LICENSE new file mode 100644 index 000000000..40f3b781b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/LICENSE @@ -0,0 +1,179 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright (c) 2009-2010 Alexis Sellier diff --git a/node_modules/grunt-contrib-less/node_modules/less/README.md b/node_modules/grunt-contrib-less/node_modules/less/README.md new file mode 100644 index 000000000..31a6a7ff8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/README.md @@ -0,0 +1,335 @@ +# [Less.js v1.5.1](http://lesscss.org) + +> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org). + +This is the JavaScript, and now official, stable version of LESS. + + +## Getting Started + +Options for adding Less.js to your project: + +* Install with [NPM](https://npmjs.org/): `npm install less` +* [Download the latest release][download] +* Clone the repo: `git clone git://github.com/less/less.js.git` + + + +## Feature Highlights +LESS extends CSS with dynamic features such as: + +* [nesting](#nesting) +* [variables](#variables) +* [operations](#operations) +* [mixins](#mixins) +* [extend](#extend) (selector inheritance) + +To learn about the many other features Less.js has to offer please visit [http://lesscss.org](http://lesscss.org) and [the Less.js wiki][wiki] + + +### Examples +#### nesting +Take advantage of nesting to make code more readable and maintainable. This: + +```less +.nav > li > a { + border: 1px solid #f5f5f5; + &:hover { + border-color: #ddd; + } +} +``` + +renders to: + +```css +.nav > li > a { + border: 1px solid #f5f5f5; +} +.nav > li > a:hover { + border-color: #ddd; +} +``` + + +#### variables +Updated commonly used values from a single location. + +```less +// Variables ("inline" comments like this can be used) +@link-color: #428bca; // appears as "sea blue" + +/* Or "block comments" that span + multiple lines, like this */ +a { + color: @link-color; // use the variable in styles +} +``` + +Variables can also be used in `@import` statements, URLs, selector names, and more. + + + +#### operations +Continuing with the same example above, we can use our variables even easier to maintain with _operations_, which enables the use of addition, subraction, multiplication and division in your styles: + +```less +// Variables +@link-color: #428bca; +@link-color-hover: darken(@link-color, 10%); + +// Styles +a { + color: @link-color; +} +a:hover { + color: @link-color-hover; +} +``` +renders to: + +```css +a { + color: #428bca; +} +a:hover { + color: #3071a9; +} +``` + +#### mixins +##### "implicit" mixins +Mixins enable you to apply the styles of one selector inside another selector like this: + +```less +// Any "regular" class... +.link { + color: @link-color; +} +a { + font-weight: bold; + .link; // ...can be used as an "implicit" mixin +} +``` + +renders to: + +```css +.link { + color: #428bca; +} +a { + font-weight: bold; + color: #428bca; +} +``` + +So any selector can be an "implicit mixin". We'll show you a DRYer way to do this below. + + + +##### parametric mixins +Mixins can also accept parameters: + +```less +// Transition mixin +.transition(@transition) { + -webkit-transition: @transition; + -moz-transition: @transition; + -o-transition: @transition; + transition: @transition; +} +``` + +used like this: + +```less +a { + font-weight: bold; + color: @link-color; + .transition(color .2s ease-in-out); + // Hover state + &:hover { + color: @link-color-hover; + } +} +``` + +renders to: + +```css +a { + font-weight: bold; + color: #428bca; + -webkit-transition: color 0.2s ease-in-out; + -moz-transition: color 0.2s ease-in-out; + -o-transition: color 0.2s ease-in-out; + transition: color 0.2s ease-in-out; +} +a:hover { + color: #3071a9; +} +``` + + +#### extend +The `extend` feature can be thought of as the _inverse_ of mixins. It accomplishes the goal of "borrowing styles", but rather than copying all the rules of _Selector A_ over to _Selector B_, `extend` copies the name of the _inheriting selector_ (_Selector B_) over to the _extending selector_ (_Selector A_). So continuing with the example used for [mixins](#mixins) above, extend works like this: + +```less +.link { + color: @link-color; +} +a:extend(.link) { + font-weight: bold; +} +// Can also be written as +a { + &:extend(.link); + font-weight: bold; +} +``` + +renders to: + +```css +.link, a { + color: #428bca; +} +``` + +## Usage + +### Compiling and Parsing +Invoke the compiler from node: + +```javascript +var less = require('less'); + +less.render('.class { width: (1 + 1) }', function (e, css) { + console.log(css); +}); +``` + +Outputs: + +```css +.class { + width: 2; +} +``` + +You may also manually invoke the parser and compiler: + +```javascript +var parser = new(less.Parser); + +parser.parse('.class { width: (1 + 1) }', function (err, tree) { + if (err) { return console.error(err) } + console.log(tree.toCSS()); +}); +``` + + +### Configuration +You may also pass options to the compiler: + +```javascript +var parser = new(less.Parser)({ + paths: ['.', './src/less'], // Specify search paths for @import directives + filename: 'style.less' // Specify a filename, for better error messages +}); + +parser.parse('.class { width: (1 + 1) }', function (e, tree) { + tree.toCSS({ compress: true }); // Minify CSS output +}); +``` + +## More information + +For general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org) or [the less wiki][wiki]. + +Here are other resources for using Less.js: + +* [stackoverflow.com][so] is a great place to get answers about Less. +* [node.js tools](https://github.com/less/less.js/wiki/Converting-LESS-to-CSS) for converting Less to CSS +* [GUI compilers for Less](https://github.com/less/less.js/wiki/GUI-compilers-that-use-LESS.js) +* [Less.js Issues][issues] for reporting bugs + + + +## Contributing +Please read [CONTRIBUTING.md](./CONTRIBUTING.md). Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). + +### Reporting Issues + +Before opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/). After that if you find a bug or would like to make feature request, [please open a new issue][issues]. + + + +### Development + +#### Install Less.js + +Start by either [downloading this project][download] manually, or in the command line: + +```shell +git clone https://github.com/less/less.js.git "less" +``` +and then `cd less`. + + +#### Install dependencies + +To install all the dependencies for less development, run: + +```shell +npm install +``` + +If you haven't run grunt before, install grunt-cli globally so you can just run `grunt` + +```shell +npm install grunt-cli -g +``` + +You should now be able to build Less.js, run tests, benchmarking, and other tasks listed in the Gruntfile. + +## Using Less.js Grunt + +Tests, benchmarking and building is done using Grunt `~0.4.1`. If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to install and use Grunt plugins, which are necessary for development with Less.js. + +The Less.js [Gruntfile](Gruntfile.js) is configured with the following "convenience tasks" : + +#### test - `grunt` +Runs jshint, nodeunit and headless jasmine tests using [phantomjs](http://code.google.com/p/phantomjs/). You must have phantomjs installed for the jasmine tests to run. + +#### test - `grunt benchmark` +Runs the benchmark suite. + +#### build for testing browser - 'grunt browser' +This builds less.js and puts it in 'test/browser/less.js' + +#### build - `grunt stable | grunt beta | grunt alpha` +Builds Less.js from from the `/lib/less` source files. This is done by the developer releasing a new release, do not do this if you are creating a pull request. + +#### readme - `grunt readme` +Build the README file from [a template](build/README.md) to ensure that metadata is up-to-date and (more likely to be) correct. + +Please review the [Gruntfile](Gruntfile.js) to become acquainted with the other available tasks. + +**Please note** that if you have any issues installing dependencies or running any of the Gruntfile commands, please make sure to uninstall any previous versions, both in the local node_modules directory, and clear your global npm cache, and then try running `npm install` again. After that if you still have issues, please let us know about it so we can help. + + +## Release History +See the [changelog](CHANGELOG) + +## [License](LICENSE) + +Copyright (c) 2009-2013 [Alexis Sellier](http://cloudhead.io/) & The Core Less Team +Licensed under the [Apache License](LICENSE). + + +[so]: http://stackoverflow.com/questions/tagged/twitter-bootstrap+less "StackOverflow.com" +[issues]: https://github.com/less/less.js/issues "GitHub Issues for Less.js" +[wiki]: https://github.com/less/less.js/wiki "The official wiki for Less.js" +[download]: https://github.com/less/less.js/zipball/master "Download Less.js" \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/benchmark/benchmark.less b/node_modules/grunt-contrib-less/node_modules/less/benchmark/benchmark.less new file mode 100644 index 000000000..bf7fef73a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/benchmark/benchmark.less @@ -0,0 +1,3979 @@ +@bg: #f01; +@white: #fff; +@grey: #eee; +@black: #000; +@blue: #000; +@accent_colour: #000; +@light_grey: #eee; +@dark_grey: #eee; +@yellow: #422; +@red: #ff0000; +@colour_positive: #ff0000; +@colour_negative: #ff0000; + +.box_shadow (...) { +} +.text_shadow (...) { +} +.border_radius (...) { +} +.border_radius_top_left (...) { +} +.border_radius_top_right (...) { +} +.border_radius_bottom_right (...) { +} +.border_radius_bottom_left (...) { +} +.border_radius_top (...) { +} +.border_radius_right (...) { +} +.border_radius_bottom (...) { +} +.border_radius_left (...) { +} +div.browse { + margin: 0 0 20px; + &.class { + padding: 0; + } + div.header { + padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; + border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; + .border_radius_top(3); color: @light_grey; + h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + .active { + background: @white; color: @black; z-index: 4; + :hover { color: @black; } + } + :hover { color: @white; } + :first-child { .border_radius_left(2); } + :last-child { .border_radius_right(2); margin-right: 0; } + } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + :last-child { + a { border: none; } + } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > ul { + margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; + li { + display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; + background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); + a.remove { + position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; + .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; + img { vertical-align: middle; } + } + div.thumbnail { + .border_radius_top(3); position: relative; z-index: 3; + .marker { + position: absolute; padding: 2px; .border_radius(2); z-index: 3; + background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; + } + .marker.coupon { + height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; + b { + display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; + border-bottom: none; border-right: none; float: left; + } + span { + color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; + padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; + } + } + .marker.video { + position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; + b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } + } + .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } + a.thumbnail { + display: block; overflow: hidden; position: relative; text-align: center; + img { position: relative; display: block; margin: auto; } + } + } + div.text { + margin: 3px 0 0; display: block; + a { text-decoration: none; } + a.title { + display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; + white-space: nowrap; height: 16px; overflow: hidden; + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + small { + font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; + a { font-weight: bold; } + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + } + :hover { + background: @accent_colour; + a.remove { display: block; } + div.thumbnail { + a.marker.remove, a.marker.video { + b { display: inline-block; } + } + a.marker.video { .box_shadow(0, 0, 2, @black); } + } + div.text { + a { color: @white; } + a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + small { + color: @white * 0.75 + @accent_colour * 0.25; + :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + } + } + div.footer a { color: @white; } + } + } + > li.ad div.thumbnail a.thumbnail { + width: 130px; height: 97px; + img { width: 100%; height: 100%; } + } + > li.brand div.thumbnail a.thumbnail { + width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); + img { max-width: 120px; max-height: 87px; } + } + li.paginate { + margin-bottom: 0; + a { + display: block; position: relative; text-decoration: none; height: 131px; + div.arrow { + background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); + height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; + b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } + } + div.label { + position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; + color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; + font-weight: bold; font-size: 12px; text-align: center; + } + :hover { + div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } + } + } + :hover { background: transparent; } + } + li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } + li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } + } + > div.footer { + padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; + border-top: 1px solid @light_grey; .border_radius_bottom(3); + div.info { + float: left; color: @grey; + strong { color: @black; font-weight: normal; } + } + div.pagination { + float: right; + > * { + display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; + .border_radius(3); text-decoration: none; font-weight: bold; + font-size: 10px; text-transform: uppercase; + } + a { color: @grey; } + a:hover { color: @black; } + span.disabled { color: @light_grey; } + span.current { color: @white; background: @bg; border: none; } + span.current:hover { color: @white; } + } + } +} +div.browse.with_categories { margin: 0 0 0 160px; } +div.browse.with_options > ul { .border_radius_top(0); } +div.browse.with_footer > ul { .border_radius_bottom(0); } +/* Browse List */ +div.browse.list { +> ul { + margin: 0; min-height: 320px; + padding: 10px 0 0 10px; overflow: hidden; + > li { + display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; + .border_radius(3); position: relative; line-height: normal; + .marker { + position: absolute; padding: 2px; .border_radius(2); + background: url('/images/transparent_backgrounds/white_75.png'); + img { height: 12px; width: 12px; } + } + img.marker { height: 12px; width: 12px; } + span.marker.new { + color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; + font-weight: bold; + } + a.marker.media_type { + display: inline-block; text-decoration: none; top: 39px; left: 8px; + font-size: 10px; + b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } + img { vertical-align: middle; } + } + a.thumbnail { + float: left; + width: 68px; display: block; overflow: hidden; + border: 1px solid @light_grey; + :hover { border-color: @accent_colour; } + } + span.title_brand { + display: block; margin: 0 0 2px 75px; + a { margin: 0; display: inline; } + a.brand_name { font-weight: normal; font-size: 12px; } + } + a.ad_title { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + a.brand_name { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + small { + display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; + } + small.brand_name { display: inline; margin: 0; } + ul.chart { + margin: 0 0 0 80px; + height: 39px; + } + ul.networks { + margin: 3px 0 0 75px; padding: 0; overflow: hidden; + li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } + } + div.points { + display: none; + font-size: 12px; text-align: right; + label { color: @grey; } + } + a.remove { bottom: -3px; right: -3px; } + } + li.ad { + a.thumbnail { height: 51px; } + span.title_brand { + small.brand_name { + display: block; + } + } + } + li.brand { + a.thumbnail { height: 68px; } + } + } +} +div.browse.list.with_options ul { .border_radius_top(0); } +div.browse.list.with_footer ul { .border_radius_bottom(0); } +div.browse.list.cols_2 { + > ul { + > li { + width: 285px; float: left; + :hover { + background: @white; + } + } + } +} +div.browse.ads.list { + > ul { + > li { + height: 53px; + a.thumbnail { + height: 51px; + } + } + } +} +div.browse.brands.list { + > ul { + > li { + height: 68px; + a.thumbnail { + height: 66px; + } + } + } +} + +/* Categories List */ +#categories { + margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; + ul { + margin: 0; padding: 10px 0 0; + li { + list-style: none; margin: 0; padding: 0; font-size: 14px; + a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } + a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } + } + .all a { font-weight: bold; } + .current a { + background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; + padding-left: 10px; + } + } +} + +/* Ads > Show */ +#ad { + div.header { + overflow: hidden; + h3 { font-size: 16px; margin: 0 0 3px; } + small { + a.category { font-weight: bold; color: @accent_colour; } + span.networks img { position: relative; top: 3px; } + } + span.brand { + float: right; color: @white; + a.brand_name { font-weight: bold; color: @accent_colour; } + } + } + div.content { + padding: 0; position: relative; + a.toggle_size { + display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; + background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; + position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; + } + img.creative { margin: 0 auto; max-width: 540px; display: block; } + object { position: relative; z-index: 44; } + object.video { line-height: 0; font-size: 0; } + object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } + } + div.content.not_video { + padding: 40px; text-align: center; + * { margin-left: auto; margin-right: auto; } + object.flash { margin-bottom: 0; } + } + div.footer { + padding: 0; + div.vote_views { + padding: 5px 10px; overflow: hidden; + div.share { float: right; margin: 2px 0 0 0; } + #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } + } + } +} +#sidebar { + #meta { + table { + margin: 0; + tr:last-child td { padding-bottom: 0; } + td { + padding: 0 0 5px; + ul.networks { + margin: 0; padding: 0; + li { + list-style: none; display: inline; + } + li { + } + } + } + td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } + } + } +} + +/* Voting */ +div.voted { + font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; + img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } +} +#voted_up { + img { background: @colour_positive * 0.66 + @bg * 0.15; } +} +#voted_down { + img { background: @colour_negative * 0.66 + @bg * 0.15; } +} +#encourage_comment { + display: inline-block; line-height: 22px; font-weight: bold; +} +#vote { + overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; + a { + color: @white; font-weight: bold; overflow: hidden; display: block; + width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; + } + a.up { + float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); + :hover { background: @colour_positive * 0.85 + @bg * 0.15; } + } + a.down { + float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); + margin: 0 5px 0 1px; + :hover { background: @colour_negative * 0.85 + @bg * 0.15; } + } +} +#vote.disabled { + a.up { + background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } + a.down { + background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } +} + +/* Panels */ +div.panel { + margin: 0 0 20px; position: relative; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); .border_radius(3); + > div.header { + background: @bg url('/images/panel_header_bg.png') repeat-x top left; border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); + padding: 5px 10px 4px; .border_radius_top(3); min-height: 18px; + h2 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + h3 { color: @white; font-size: 14px; margin: 0; line-height: 18px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + small { display: block; font-size: 12px; color: @light_grey * 0.25 + @white * 0.75; } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + } + a:first-child { .border_radius_left(2); } + a:last-child { .border_radius_right(2); margin-right: 0; } + a.active { background: @white; color: @black; z-index: 4; } + a:hover { color: @white; } + a.active:hover { color: @black; } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + } + li:last-child { + a { border: none; } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > div.content { + background: @white; padding: 10px; + .no_padding { padding: 0; } + } + > div.footer { + background: @light_grey * 0.33 + @white * 0.66; border-top: 1px solid (@light_grey * 0.5 + @white * 0.5); + padding: 4px 10px 5px; .border_radius_bottom(3); + } +} +div.panel.no_footer div.content { .border_radius_bottom(3); } +div.panel.no_header div.content { .border_radius_top(3); } +div.panel.collapsable { + div.header { + cursor: pointer; + b.toggle { float: right; border: 5px solid transparent; border-bottom: 5px solid @white; border-top: none; display: block; width: 0; height: 0; margin: 6px 0 0 0; } + } + div.header:hover { + background-color: @bg * 0.75 + @white * 0.25; + } +} +div.panel.collapsed { + div.header { + border-bottom: none; .border_radius(3); + b.toggle { border-bottom: none; border-top: 5px solid @white; } + } + div.blank { border-bottom: none; .border_radius_bottom(3); } + div.content, div.footer { display: none; } +} + + +/* Sidebar Actions */ +#sidebar { + #actions { + .box_shadow(0, 0, 0, transparent); + div.content { + background: url('/images/transparent_backgrounds/accent_colour_10.png'); text-align: center; + p.endorsement { + margin: 0 0 10px; font-size: 14px; font-weight: bold; + small { font-weight: normal; line-height: inherit; margin: 10px 0 0; } + :last-child { margin: 0; } + } + div.share { margin: 5px 0 0; } + a.button { + font-size: 16px; line-height: normal; height: auto; padding: 5px 10px 5px 35px; font-weight: bold; margin: 0; position: relative; + img { position: absolute; top: 3px; left: 6px; } + } + div.flash.notice { + margin: 10px 0 0; font-size: 22px; + small { font-weight: normal; margin: 0 0 10px; } + } + div.flash.notice.done { margin: 0; } + small { + display: block; margin: 10px 0 0; font-size: 11px; color: #808080; line-height: 12px; + img.favicon { vertical-align: middle; } + } + div.blank { + border: none; background: none; padding: 10px 0 0; border-top: 1px solid (@accent_colour * 0.5 + @white * 0.5); + margin: 10px 0 0; + } + } + } +} + +/* People Lists */ +ul.people { + margin: 0; padding: 10px 0 0 10px; background: @white; + > li { + display: block; margin: 0 10px 10px 0; float: left; padding: 2px; width: 57px; position: relative; + .border_radius(2); background: @white; list-style: none; border: 1px solid (@light_grey * 0.33 + @white * 0.66); + a.avatar { + display: block; width: 59px; height: 59px; overflow: hidden; + img { width: 100%; height: 100%; } + } + a.name { display: block; font-size: 10px; text-align: center; } + :hover { + background: @accent_colour; + a.name { color: @white; } + } + } +} +ul.people.list { + padding: 0; + > li { + margin: 0 0 10px; padding: 0 0 10px; overflow: hidden; float: none; width: auto; .border_radius(0); + border: none; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); + span.points { + float: right; display: block; padding: 5px; background: @light_grey * 0.15 + @white * 0.85; line-height: 1; + text-align: center; width: 50px; height: 30px; .border_radius(3); margin: 0 0 0 10px; + strong { display: block; color: @black; font-size: 16px; margin: 2px 0 0; } + label { color: @grey; text-transform: uppercase; font-size: 10px; } + label.long { display: block; } + label.short { display: none; } + } + a.avatar { float: left; width: 40px; height: 40px; } + a.name { font-size: 14px; font-weight: bold; margin: 0 0 0 50px; text-align: left; } + a.name.long { display: inline; } + a.name.short { display: none; } + span.networks { + display: block; margin: 0 0 0 50px; + img.favicon { vertical-align: middle; } + } + :hover { + background: transparent; + a.name { color: @accent_colour * 0.85 + @black * 0.15; } + } + :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } + } +} +ul.people.list.small { + > li { + span.points { + padding: 3px 6px; height: 18px; font-size: 9px; line-height: 17px; width: 60px; + strong { font-size: 12px; margin: 0; display: inline; } + label { font-size: 9px; } + label.long { display: none; } + label.short { display: inline; } + } + a.avatar { width: 24px; height: 24px; } + a.name { display: inline; line-height: 24px; margin: 0 0 0 5px; font-size: 12px; height: 24px; } + a.name.long { display: none; } + a.name.short { display: inline; } + span.networks { display: inline; margin: 0; } + :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } + } +} +ul.people.tiled { + > li { + width: 28px; padding: 2px; + a.avatar { width: 24px; height: 24px; background: @white; padding: 2px; } + a.name, small, span.networks, span.points { display: none; } + } +} + +/* Comments */ +#comments { + ul { + margin: 0 0 20px; padding: 0; + li { + display: block; list-style: none; padding: 0; margin: 0 0 10px; + span.meta { + margin: 0; overflow: hidden; display: block; + small { font-size: 12px; color: @light_grey; float: right; line-height: 16px; display: inline-block; } + a.avatar { + display: inline-block; height: 16px; width: 16px; position: relative; top: 3px; + img { height: 100%; width: 100%; } + } + a.name { font-weight: bold; line-height: 16px; display: inline-block; } + span.inactive { color: @grey; font-weight: bold; line-height: 16px; display: inline-block; } + } + b.tail { + display: block; width: 0; height: 0; margin: 3px 0 0 10px; border: 5px solid transparent; border-top: none; + border-bottom: 5px solid @white; position: relative; z-index: 2; + } + blockquote { + margin: 0; padding: 10px; .border_radius(3); font-style: normal; background: @white; + color: @dark_grey; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); + } + } + } + form { + margin: 0; + textarea { width: 500px; } + } +} + +/* Sidebar Categories */ +#sidebar { + #categories { + margin: 0 0 20px; + width: auto; + p { margin: 0; } + } +} + +#sidebar { + #ads > ul li, #recommendations > ul li { + width: 81px; + div.thumbnail { + a.thumbnail { height: 60px; width: 81px; } + } + div.text { + a.title { font-size: 11px; height: 14px; line-height: 14px; } + small { display: none; } + } + } + #brands > ul li { + width: 55px; + div.thumbnail { + a.thumbnail { + height: 45px; width: 45px; + img { max-height: 45px; max-width: 45px; } + } + } + div.text { display: none; } + } +} + +/* My Account */ +#accounts_controller { + #top { + #page_title { + #page_options { + a.button.public_profile { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } + } + a.button.goto_dashboard { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } + } + } + } + } + #account_nav { + float: left; width: 200px; margin: 0 20px 0 0; + ul.nav { + margin: 0; padding: 0; + li { + margin: 0 0 5px; display: block; list-style: none; padding: 0; + a { + display: block; height: 30px; text-decoration: none; color: @white; + b { + border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; + height: 0; float: right; display: none; + } + span { + .border_radius(3); background: @bg; display: block; + line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; + } + } + :hover { + a { + color: @white; + b { border-left-color: @bg; display: block; } + span { background: @bg; .border_radius_right(0); } + } + } + } + li.current a { + b { border-left-color: @accent_colour; display: block; } + span { background: @accent_colour; color: @white; .border_radius_right(0); } + } + } + } + #main { + > div { + margin: 0 0 20px; + form { margin: 0; } + } + #profile { + a.avatar { + float: left; display: block; + width: 70px; overflow: hidden; position: relative; text-decoration: none; + img { width: 100%; } + span { + display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; + .border_radius(3); .text_shadow(1, 1, 0, @grey); + text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; + } + } + form { + margin: 0 0 0 90px; + h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } + ul.choices { + li { width: 30%; } + } + div.extra { margin-top: 20px; } + } + } + + #networks { + ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; + li:hover + { + background: @light_grey; display: block; float: left; width: 180px; + padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); + position: relative; + * { line-height: normal; } + img { vertical-align: middle; float: left; } + .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } + small { + font-size: 12px; color: @grey; display: block; margin-left: 42px; + strong { color: @black; font-weight: normal; } + } + :hover { + } + } + li.installed { + background: @white; + border: 2px solid @accent_colour; padding: 8px; + } + li.unavailable { + .name { color: @black; } + :hover { + background: @light_grey; + } + } + li:hover { + background: @light_grey * 0.5 + @white * 0.5; + } + } + } + } +} + +/* Shopping Style Panel */ +#shopping_style { + div.header a.button.small { float: right; } + div.content { + p { + margin: 0 0 10px; + label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } + span { color: @black; } + span.toggle { white-space: nowrap; color: @grey; } + :last-child { margin: 0; } + } + p.more { text-align: left; font-weight: normal; } + p.less { display: none; margin: 0; } + } +} + +/* People Controller */ +#people_controller.index { + #main { + div.panel { + float: left; width: 300px; margin: 0 20px 0 0; + :last-child { margin-right: 0; } + } + } +} +#people_controller.show { + #person_overview, #shopping_style { + a.button.small { + } + } + #content { + #shopping_style { + float: left; width: 240px; margin: 0 20px 0 0; + } + #main { width: 360px; } + } +} + +/* Search Results */ +#search_results { + margin: 0 0 20px; + li { + :hover { + small { color: @white * 0.75 + @accent_colour * 0.25; } + } + } +} +#search { + div.content { + padding: 20px; + form { + margin: 0; float: none; + span.submit_and_options { + display: block; + } + } + p { margin: 0 0 15px; } + h4 { font-weight: normal; margin: 0 0 5px; } + } +} + +/* Recommendations */ +#recommendations { + div.browse { + margin: 0; padding: 0; background: none; + ul { min-height: 0; .border_radius(0); } + } +} + +/* Blank States */ +div.blank { + padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; + border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; + h4 { font-size: 18px; margin: 0 0 10px; } + h4:last-child { margin: 0; } + p { font-size: 16px; margin: 0 0 10px; } + p:last-child { margin: 0; } + p.with_list_number.large { + span { margin-left: 48px; display: block; color: @white; } + } + p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } + a { white-space: nowrap; } + a.hide { + position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); + } +} + +div.blank.small { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 16px; } + p { margin: 0; } +} +div.blank.tiny { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 14px; } + p { margin: 0; font-size: 12px; } +} +div.blank.rounded { + .border_radius(3); margin: 0 0 20px; +} +div.blank.rounded.bottom { .border_radius_top(0); } +div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } +div.blank.no_border_top { border-top: none; } +div.blank.no_border_bottom { border-bottom: none; } +div.blank.no_side_borders { border-right: none; border-left: none; } +div.panel { + div.blank { + padding: 10px 20px; overflow: hidden; margin: 0; + h4 { font-weight: normal; font-size: 14px; } + p, ul { margin: 0 0 10px; font-size: 12px; } + p:last-child, ul:last-child { margin: 0; } + } +} + +/* Sidebar Browse */ +#sidebar { + div.panel { + div.content.browse { + padding: 0; margin: 0; + > ul { + min-height: 0; .border_radius(0); + > li { + div.thumbnail { + a.thumbnail { padding: 5px; } + img.marker.media_type { top: 48px; left: 8px; } + } + div.footer { + a.title, a.name { font-size: 11px; font-weight: normal; } + } + } + } + } + + div.content.browse.ads > ul > li { + width: 93px; + > div.thumbnail a.thumbnail { width: 83px; height: 62px; } + } + div.content.browse.brands { + .border_radius(3); + > ul { + background: none; + > li { + width: 52px; + > div.thumbnail { + padding: 3px; + a.thumbnail { width: 42px; height: 42px; padding: 2px; } + } + li.active { background: @accent_colour; } + } + } + } + div.footer { + div.info { float: none; } + div.pagination { float: none; margin: 3px 0 0; } + } + } +} + +/* List Numbers */ +label.list_number { + float: left; background: url('/images/transparent_backgrounds/black_15.png'); padding: 2px; width: 24px; height: 24px; display: block; + .border_radius(99); + b { + display: block; font-weight: bold; font-size: 14px; color: @white; background: @accent_colour; height: 20px; width: 20px; line-height: 20px; + text-align: center; .border_radius(99); .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); + border: 2px solid @white; + } +} +label.list_number.large { + padding: 4px; width: 48px; height: 48px; .border_radius(99); position: relative; left: -10px; + b { + font-size: 28px; height: 40px; width: 40px; .border_radius(99); line-height: 40px; + .text_shadow(2, 2, 0px, (@accent_colour * 0.75 + @black * 0.25)); border-width: 4px; + } +} + +/* Dashboard */ +#dashboard_controller { + #ads { + span.filter.state { float: right; } + } + #sidebar { + #shopping_style div.content { + p.less { display: block; } + p.more { display: none; } + } + #influences { + div.header { + padding-bottom: 0; + ul.tabs { + position: relative; top: 1px; z-index: 3; + li { + margin: 0 5px 0 0; + a { + border: none; background: url('/images/transparent_backgrounds/white_75.png'); + :hover { color: @black; } + } + } + li.active { + a { + background: @white; border: none; + :hover { color: @black; } + } + } + } + } + + div.tab_content { + overflow: hidden; padding: 0; + > ul { + padding: 10px 10px 0; max-height: 280px; min-height: 120px; overflow-y: scroll; .border_radius_bottom(3px); + } + } + div.footer { + form { + p { + margin: 0 0 5px; + img.marker { float: right; margin: 5px 0 0 0; } + span.invitee { + line-height: 26px; padding: 3px 3px 0; font-size: 14px; + small { color: @grey; font-size: 12px; } + } + } + p.indent { margin-left: 36px; } + p.submit { margin-top: 10px; } + } + } + } + } + + div.panel.full { + > div.content { + margin: 0; padding: 0; background: none; + ul { + li { + width: 148px; + div.thumbnail { + img.marker.media_type { top: 90px; } + a.thumbnail { width: 138px; height: 104px; } + } + } + } + } + } + #people { + form { + padding: 0 0 5px; + input { width: 225px; float: left; margin: 0 5px 0 0; } + a.button { height: 23px; line-height: 23px; width: 60px; padding: 0; text-align: center; } + } + } +} + +/* Remove Pages Titles when Browsing */ +#ads_controller, #brands_controller { + #page_title { display: none; } +} + +/* Brands > Show */ +#brands_controller.show { + #ads { + div.filters { + h3 { font-size: 16px; margin: 0; } + span.show { float: right; } + span.filter.dropdown.localisation { float: right; margin: 0 0 0 10px; } + span.filter.state { float: right; margin: 0 0 0 10px; } + } + } +} + +/* FAQ */ +#pages_controller.faq { + #answers { + h3 { margin-top: 20px; padding-top: 20px; border-top: 1px solid (@light_grey * 0.75 + @white * 0.25); } + h3.first { margin-top: 0; padding-top: 0; border: none; } + } + #questions { + div.content { + padding: 20px; + ul { + margin: 0; padding: 0; + li { + margin: 0 0 10px; list-style: none; display: block; padding: 0; + a { font-size: 14px; } + } + li:last-child { + margin: 0; + } + } + } + } +} + +/* Person Overview */ +#person_overview { + padding: 20px 10px; position: relative; z-index: 25; + #person { + float: left; width: 620px; + a.avatar { + display: block; float: left; width: 60px; height: 60px; + img { height: 100%; width: 100%; } + } + > div { + margin: 0 0 0 75px; color: @white; font-size: 14px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + } + div.name { + h2 { + margin: 0 0 5px; display: inline; + a { + font-size: 20px; font-weight: bold; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + line-height: 1; color: @white; text-decoration: none; + :hover { text-decoration: underline; } + } + a.button.small { + font-size: 10px; + :hover { text-decoration: none; } + } + } + + span.points { + float: right; display: block; padding: 5px 10px; .border_radius(2); text-align: center; background: @white; position: relative; + min-width: 45px; + strong { color: @black; font-weight: bold; font-size: 24px; line-height: 1; display: block; .text_shadow(0, 0, 0, transparent); } + label { font-size: 9px; text-transform: uppercase; color: @grey; display: block; .text_shadow(0, 0, 0, transparent); font-weight: bold; } + } + span.points.with_redeem { + .border_radius_bottom(0); + a.button { + display: block; text-align: center; .border_radius_top(0); font-size: 10px; font-weight: bold; padding: 0; + position: absolute; height: 18px; left: 0; right: 0; bottom: -19px; line-height: 18px; text-transform: uppercase; border: none; + } + } + div.options { margin: 0; } + } + div.meta { + color: @white * 0.66 + @bg * 0.33; + span { color: @white; } + label { color: @white * 0.66 + @bg * 0.33; } + ul.networks { + display: inline; margin: 0; padding: 0; + li { + display: inline; line-height: 1; + img { position: relative; vertical-align: middle; top: -1px; } + } + } + } + + div.extra { + font-size: 12px; margin-top: 20px; margin-bottom: 20px; + span.toggle { + .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + a { font-size: 10px; font-weight: bold; text-transform: uppercase; text-decoration: none; color: @accent_colour; } + b.arrow { display: inline-block; width: 0; height: 0; border: 5px solid transparent; position: relative; top: -2px; } + } + #less_info { + span.toggle { + b.arrow { border-top: 5px solid @accent_colour; border-bottom: 0; } + } + } + #more_info { + span.toggle { + float: right; + b.arrow { border-bottom: 5px solid @accent_colour; border-top: 0; } + } + h4 { + color: @white; margin: 0 0 10px 0; border-bottom: 1px solid (@white * 0.25 + @bg * 0.75); .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); + span { font-size: 12px; } + } + p { + margin: 0 0 5px; + label { display: block; float: left; width: 120px; color: @white * 0.66 + @bg * 0.33; } + span { display: block; margin: 0 0 0 130px; } + } + p:last-child { margin: 0; } + + } + } + div.login { + margin: 0 0 0 75px; + a.button { font-weight: bold; } + } + } +} + +/* Dashboard Nav */ +#dashboard_nav { + position: absolute; bottom: 0; left: 10px; margin: 0; padding: 0; overflow: hidden; + li { + display: block; float: left; margin: 0 5px 0 0; + a { + display: block; height: 28px; padding: 0 10px; line-height: 28px; .border_radius_top(2); + text-decoration: none; color: @white; background: url('/images/transparent_backgrounds/accent_colour_30.png'); font-size: 14px; + font-weight: bold; + :hover { background: url('/images/transparent_backgrounds/accent_colour_45.png'); } + } + } + li.active { + a { + background: @white; color: @black; + :hover { color: @black; } + } + } +} + +/* Dwellometer */ +#dwellometer { + z-index: 45; float: right; .box_shadow(0, 0, 0, transparent); margin: 0; + div.content { + text-align: center; position: relative; + object, object embed { position: relative; z-index: 46; line-height: 0; } + div.title { + position: absolute; bottom: 10px; left: 0; right: 0; z-index: 50; + img { width: 120px; display: block; margin: 0 auto; position: relative; left: -5px; } + } + } +} + +/* Activity Stream */ +#activity { + div.content { + ul.events { + padding: 0; margin: 0 0 -10px; + li { + margin: 0; padding: 10px 0; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); + list-style: none; overflow: hidden; + small.meta { + font-size: 12px; color: @light_grey; float: right; + } + a.button { float: right; margin: 0 0 10px 10px; } + a.avatar, a.logo, a.thumbnail { + height: 32px; display: block; float: left; + img { width: 100%; height: 100%; } + } + a.avatar, a.logo, a.icon { width: 32px; } + a.thumbnail { width: 42px; } + div.symbols { + float: left; overflow: hidden; + b { + display: block; float: left; margin: 10px 5px 0; + img { height: 12px; width: 12px; } + } + b.voted { margin: 10px 3px 0; padding: 2px; .border_radius(2); } + b.voted.for { background: @colour_positive * 0.33 + @white * 0.66; } + b.voted.against { background: @colour_negative * 0.33 + @white * 0.66; } + } + /* Temporarily removed avatar and symbol */ +/* div.symbols a.agent, b { display: none; }*/ + div.description { + font-size: 12px; color: @grey; + a.agent { font-weight: bold; } + } + div.comment { + margin-top: 2px; + b.tail { + display: block; margin: 0 0 0 10px; width: 0; height: 0; border: 5px solid transparent; + border-top: none; border-bottom: 5px solid (@light_grey * 0.25 + @white * 0.75); + } + blockquote { + margin: 0; font-style: normal; color: @dark_grey; + .border_radius(3); background: @light_grey * 0.25 + @white * 0.75; padding: 5px 10px; + span.view_comment { + color: @grey; + } + } + } + div.content { + overflow: hidden; + } + } + li.new_comment.ad, li.endorsed.ad, li.voted { + div.description, div.content { margin-left: 106px; } +/* div.description, div.content { margin-left: 53px; }*/ + } + li.new_comment.brand, li.replied_to, li.endorsed.brand, li.connected, li.sn_setup { + div.description, div.content { margin-left: 96px; } +/* div.description, div.content { margin-left: 43px; }*/ + } + li.replied_to { + div.content { + a.thumbnail, a.logo { margin-top: 7px; } + } + } + li.replied_to.ad { + div.content { + div.comment { margin-left: 52px; } + } + } + li.replied_to.brand { + div.content { + div.comment { margin-left: 42px; } + } + } + li.voted div.description span.action { .border_radius(2); color: @dark_grey; padding: 0 3px; white-space: nowrap; } + li.voted.for div.description span.action { background: @colour_positive * 0.15 + @white * 0.85; } + li.voted.against div.description span.action { background: @colour_negative * 0.15 + @white * 0.85; } + li:first-child { padding-top: 0; } + li:last-child { border-bottom: none; } + li:hover div.content div.comment blockquote span.view_comment { + } + } + } +} + +/* Login/Register Modal */ +#login_register { + div.location_select, + div.location_search { margin-left: 130px; } + h3 { + small { font-size: 14px; font-weight: normal; display: block; color: @grey; text-align: left; margin: 0; display: block; } + } +} + +/* Contact Form in Pages */ +#pages_controller { + #sidebar { + #contact { + margin: 15px 0 0; + form { + label { text-align: left; float: none; width: auto; font-size: 12px; font-weight: bold; line-height: 1; margin: 0 0 5px; } + p.submit.indent { + margin: 0; + span.with_cancel { display: none; } + } + } + } + } +} + +/* Exclusive Offers */ +#offers { + div.content { + a.gift { + display: block; text-align: center; + img { height: 100px; } + } + } +} + +div.browse { + margin: 0 0 20px; + &.class { + padding: 0; + } + div.header { + padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; + border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; + .border_radius_top(3); color: @light_grey; + h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } + span.filter { + float: left; display: block; overflow: hidden; position: relative; z-index: 5; + a { + margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; + text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; + .active { + background: @white; color: @black; z-index: 4; + :hover { color: @black; } + } + :hover { color: @white; } + :first-child { .border_radius_left(2); } + :last-child { .border_radius_right(2); margin-right: 0; } + } + } + + span.filter.dropdown { + margin: 0; position: relative; overflow: visible; + a { + .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; + img { float: left; margin: 4px 5px 0 0; } + b.arrow { + float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; + position: absolute; top: 6px; right: 10px; + } + :hover { + background: @accent_colour; color: @white; + b.arrow { border-top: 5px solid @white; } + } + } + ul { + position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); + .box_shadow(0, 1, 1, @black); + li { + list-style: none; display: block; padding: 0; margin: 0; + a { + display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; + border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; + :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } + } + :last-child { + a { border: none; } + } + } + } + } + span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } + span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } + a.more { + float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; + position: relative; top: 2px; + :hover { text-decoration: none; } + } + } + > ul { + margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; + li { + display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; + background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); + a.remove { + position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; + .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; + img { vertical-align: middle; } + } + div.thumbnail { + .border_radius_top(3); position: relative; z-index: 3; + .marker { + position: absolute; padding: 2px; .border_radius(2); z-index: 3; + background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; + } + .marker.coupon { + height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; + b { + display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; + border-bottom: none; border-right: none; float: left; + } + span { + color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; + padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; + } + } + .marker.video { + position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; + b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } + } + .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } + a.thumbnail { + display: block; overflow: hidden; position: relative; text-align: center; + img { position: relative; display: block; margin: auto; } + } + } + div.text { + margin: 3px 0 0; display: block; + a { text-decoration: none; } + a.title { + display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; + white-space: nowrap; height: 16px; overflow: hidden; + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + small { + font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; + a { font-weight: bold; } + :before { + display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; + background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); + } + } + } + :hover { + background: @accent_colour; + a.remove { display: block; } + div.thumbnail { + a.marker.remove, a.marker.video { + b { display: inline-block; } + } + a.marker.video { .box_shadow(0, 0, 2, @black); } + } + div.text { + a { color: @white; } + a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + small { + color: @white * 0.75 + @accent_colour * 0.25; + :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } + } + } + div.footer a { color: @white; } + } + } + > li.ad div.thumbnail a.thumbnail { + width: 130px; height: 97px; + img { width: 100%; height: 100%; } + } + > li.brand div.thumbnail a.thumbnail { + width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); + img { max-width: 120px; max-height: 87px; } + } + li.paginate { + margin-bottom: 0; + a { + display: block; position: relative; text-decoration: none; height: 131px; + div.arrow { + background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); + height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; + b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } + } + div.label { + position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; + color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; + font-weight: bold; font-size: 12px; text-align: center; + } + :hover { + div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } + } + } + :hover { background: transparent; } + } + li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } + li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } + } + > div.footer { + padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; + border-top: 1px solid @light_grey; .border_radius_bottom(3); + div.info { + float: left; color: @grey; + strong { color: @black; font-weight: normal; } + } + div.pagination { + float: right; + > * { + display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; + .border_radius(3); text-decoration: none; font-weight: bold; + font-size: 10px; text-transform: uppercase; + } + a { color: @grey; } + a:hover { color: @black; } + span.disabled { color: @light_grey; } + span.current { color: @white; background: @bg; border: none; } + span.current:hover { color: @white; } + } + } +} +div.browse.with_categories { margin: 0 0 0 160px; } +div.browse.with_options > ul { .border_radius_top(0); } +div.browse.with_footer > ul { .border_radius_bottom(0); } +/* Browse List */ +div.browse.list { +> ul { + margin: 0; min-height: 320px; + padding: 10px 0 0 10px; overflow: hidden; + > li { + display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; + .border_radius(3); position: relative; line-height: normal; + .marker { + position: absolute; padding: 2px; .border_radius(2); + background: url('/images/transparent_backgrounds/white_75.png'); + img { height: 12px; width: 12px; } + } + img.marker { height: 12px; width: 12px; } + span.marker.new { + color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; + font-weight: bold; + } + a.marker.media_type { + display: inline-block; text-decoration: none; top: 39px; left: 8px; + font-size: 10px; + b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } + img { vertical-align: middle; } + } + a.thumbnail { + float: left; + width: 68px; display: block; overflow: hidden; + border: 1px solid @light_grey; + :hover { border-color: @accent_colour; } + } + span.title_brand { + display: block; margin: 0 0 2px 75px; + a { margin: 0; display: inline; } + a.brand_name { font-weight: normal; font-size: 12px; } + } + a.ad_title { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + a.brand_name { + font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; + } + small { + display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; + } + small.brand_name { display: inline; margin: 0; } + ul.chart { + margin: 0 0 0 80px; + height: 39px; + } + ul.networks { + margin: 3px 0 0 75px; padding: 0; overflow: hidden; + li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } + } + div.points { + display: none; + font-size: 12px; text-align: right; + label { color: @grey; } + } + a.remove { bottom: -3px; right: -3px; } + } + li.ad { + a.thumbnail { height: 51px; } + span.title_brand { + small.brand_name { + display: block; + } + } + } + li.brand { + a.thumbnail { height: 68px; } + } + } +} +div.browse.list.with_options ul { .border_radius_top(0); } +div.browse.list.with_footer ul { .border_radius_bottom(0); } +div.browse.list.cols_2 { + > ul { + > li { + width: 285px; float: left; + :hover { + background: @white; + } + } + } +} +div.browse.ads.list { + > ul { + > li { + height: 53px; + a.thumbnail { + height: 51px; + } + } + } +} +div.browse.brands.list { + > ul { + > li { + height: 68px; + a.thumbnail { + height: 66px; + } + } + } +} + +/* Categories List */ +#categories { + margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; + ul { + margin: 0; padding: 10px 0 0; + li { + list-style: none; margin: 0; padding: 0; font-size: 14px; + a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } + a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } + } + .all a { font-weight: bold; } + .current a { + background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; + padding-left: 10px; + } + } +} + +/* Ads > Show */ +#ad { + div.header { + overflow: hidden; + h3 { font-size: 16px; margin: 0 0 3px; } + small { + a.category { font-weight: bold; color: @accent_colour; } + span.networks img { position: relative; top: 3px; } + } + span.brand { + float: right; color: @white; + a.brand_name { font-weight: bold; color: @accent_colour; } + } + } + div.content { + padding: 0; position: relative; + a.toggle_size { + display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; + background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; + position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; + } + img.creative { margin: 0 auto; max-width: 540px; display: block; } + object { position: relative; z-index: 44; } + object.video { line-height: 0; font-size: 0; } + object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } + } + div.content.not_video { + padding: 40px; text-align: center; + * { margin-left: auto; margin-right: auto; } + object.flash { margin-bottom: 0; } + } + div.footer { + padding: 0; + div.vote_views { + padding: 5px 10px; overflow: hidden; + div.share { float: right; margin: 2px 0 0 0; } + #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } + } + } +} +#sidebar { + #meta { + table { + margin: 0; + tr:last-child td { padding-bottom: 0; } + td { + padding: 0 0 5px; + ul.networks { + margin: 0; padding: 0; + li { + list-style: none; display: inline; + } + li { + } + } + } + td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } + } + } +} + +/* Voting */ +div.voted { + font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; + img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } +} +#voted_up { + img { background: @colour_positive * 0.66 + @bg * 0.15; } +} +#voted_down { + img { background: @colour_negative * 0.66 + @bg * 0.15; } +} +#encourage_comment { + display: inline-block; line-height: 22px; font-weight: bold; +} +#vote { + overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; + a { + color: @white; font-weight: bold; overflow: hidden; display: block; + width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; + } + a.up { + float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); + :hover { background: @colour_positive * 0.85 + @bg * 0.15; } + } + a.down { + float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); + margin: 0 5px 0 1px; + :hover { background: @colour_negative * 0.85 + @bg * 0.15; } + } +} +#vote.disabled { + a.up { + background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } + a.down { + background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; + :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } + } +} +#sidebar { + #ads > ul li, #recommendations > ul li { + width: 81px; + div.thumbnail { + a.thumbnail { height: 60px; width: 81px; } + } + div.text { + a.title { font-size: 11px; height: 14px; line-height: 14px; } + small { display: none; } + } + } + #brands > ul li { + width: 55px; + div.thumbnail { + a.thumbnail { + height: 45px; width: 45px; + img { max-height: 45px; max-width: 45px; } + } + } + div.text { display: none; } + } +} + +/* My Account */ +#accounts_controller { + #top { + #page_title { + #page_options { + a.button.public_profile { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } + } + a.button.goto_dashboard { + float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; + b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } + } + } + } + } + #account_nav { + float: left; width: 200px; margin: 0 20px 0 0; + ul.nav { + margin: 0; padding: 0; + li { + margin: 0 0 5px; display: block; list-style: none; padding: 0; + a { + display: block; height: 30px; text-decoration: none; color: @white; + b { + border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; + height: 0; float: right; display: none; + } + span { + .border_radius(3); background: @bg; display: block; + line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; + } + } + :hover { + a { + color: @white; + b { border-left-color: @bg; display: block; } + span { background: @bg; .border_radius_right(0); } + } + } + } + li.current a { + b { border-left-color: @accent_colour; display: block; } + span { background: @accent_colour; color: @white; .border_radius_right(0); } + } + } + } + #main { + > div { + margin: 0 0 20px; + form { margin: 0; } + } + #profile { + a.avatar { + float: left; display: block; + width: 70px; overflow: hidden; position: relative; text-decoration: none; + img { width: 100%; } + span { + display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; + .border_radius(3); .text_shadow(1, 1, 0, @grey); + text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; + } + } + form { + margin: 0 0 0 90px; + h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } + ul.choices { + li { width: 30%; } + } + div.extra { margin-top: 20px; } + } + } + + #networks { + ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; + li:hover + { + background: @light_grey; display: block; float: left; width: 180px; + padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); + position: relative; + * { line-height: normal; } + img { vertical-align: middle; float: left; } + .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } + small { + font-size: 12px; color: @grey; display: block; margin-left: 42px; + strong { color: @black; font-weight: normal; } + } + :hover { + } + } + li.installed { + background: @white; + border: 2px solid @accent_colour; padding: 8px; + } + li.unavailable { + .name { color: @black; } + :hover { + background: @light_grey; + } + } + li:hover { + background: @light_grey * 0.5 + @white * 0.5; + } + } + } + } +} + +/* Shopping Style Panel */ +#shopping_style { + div.header a.button.small { float: right; } + div.content { + p { + margin: 0 0 10px; + label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } + span { color: @black; } + span.toggle { white-space: nowrap; color: @grey; } + :last-child { margin: 0; } + } + p.more { text-align: left; font-weight: normal; } + p.less { display: none; margin: 0; } + } +} + +/* People Controller */ +#people_controller.index { + #main { + div.panel { + float: left; width: 300px; margin: 0 20px 0 0; + :last-child { margin-right: 0; } + } + } +} +#people_controller.show { + #person_overview, #shopping_style { + a.button.small { + } + } + #content { + #shopping_style { + float: left; width: 240px; margin: 0 20px 0 0; + } + #main { width: 360px; } + } +} + +/* Search Results */ +#search_results { + margin: 0 0 20px; + li { + :hover { + small { color: @white * 0.75 + @accent_colour * 0.25; } + } + } +} +#search { + div.content { + padding: 20px; + form { + margin: 0; float: none; + span.submit_and_options { + display: block; + } + } + p { margin: 0 0 15px; } + h4 { font-weight: normal; margin: 0 0 5px; } + } +} + +/* Recommendations */ +#recommendations { + div.browse { + margin: 0; padding: 0; background: none; + ul { min-height: 0; .border_radius(0); } + } +} + +/* Blank States */ +div.blank { + padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; + border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; + h4 { font-size: 18px; margin: 0 0 10px; } + h4:last-child { margin: 0; } + p { font-size: 16px; margin: 0 0 10px; } + p:last-child { margin: 0; } + p.with_list_number.large { + span { margin-left: 48px; display: block; color: @white; } + } + p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } + a { white-space: nowrap; } + a.hide { + position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); + } +} + +div.blank.small { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 16px; } + p { margin: 0; } +} +div.blank.tiny { + padding: 10px 20px; + h4 { font-weight: normal; font-size: 14px; } + p { margin: 0; font-size: 12px; } +} +div.blank.rounded { + .border_radius(3); margin: 0 0 20px; +} +div.blank.rounded.bottom { .border_radius_top(0); } +div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } +div.blank.no_border_top { border-top: none; } +div.blank.no_border_bottom { border-bottom: none; } +div.blank.no_side_borders { border-right: none; border-left: none; } +div.panel { + div.blank { + padding: 10px 20px; overflow: hidden; margin: 0; + h4 { font-weight: normal; font-size: 14px; } + p, ul { margin: 0 0 10px; font-size: 12px; } + p:last-child, ul:last-child { margin: 0; } + } +} + +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: @r * 10; +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + .spacing { + height: 10px / 2px+6px-1px*2; + width: 2 * 4-5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6px * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width: (@var * @var) * 6; + height: (7 * 7) + (8 * 8); + margin: 4 * (5 + 5) / 2 - (@var * 2); + //margin: (6 * 6)px; +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2+3)*(2+3) / (9-4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} + +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +}h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; +} +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + font-family: @a, @a, @a; +} + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: @r * 10; +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} +#operations { + color: #110000 + #000011 + #001100; // #111111 + height: 10px / 2px + 6px - 1px * 2; // 9px + width: 2 * 4 - 5em; // 3em + .spacing { + height: 10px / 2px+6px-1px*2; + width: 2 * 4-5em; + } + substraction: 20 - 10 - 5 - 5; // 0 + division: 20 / 5 / 4; // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: @x + @y; // 16em + width: 12 + @y; // 24em + size: 5cm - @x; // 1cm +} + +@z: -2; + +.negative { + height: 2px + @z; // 0px + width: 2px - @z; // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.colors { + color: #123; // #112233 + border-color: #234 + #111111; // #334455 + background-color: #222222 - #fff; // #000000 + .other { + color: 2 * #111; // #222222 + border-color: #333333 / 3 + #111; // #222222 + } +} +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6px * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width: (@var * @var) * 6; + height: (7 * 7) + (8 * 8); + margin: 4 * (5 + 5) / 2 - (@var * 2); + //margin: (6 * 6)px; +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2+3)*(2+3) / (9-4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} + +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +}h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; +} +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + font-family: @a, @a, @a; +} + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } +} + +#overflow { + .a { color: #111111 - #444444; } // #000000 + .b { color: #eee + #fff; } // #ffffff + .c { color: #aaa * 3; } // #ffffff + .d { color: #00ee00 + #009900; } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +#last { color: blue } +// +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; +} +@font-face { + font-family: Headline; + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + font-size: 3em; +} + +@media screen { + font-size: 10px; +} + +@font-face { + font-family: 'Garamond Pro'; + src: url("/fonts/garamond-pro.ttf"); +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: 2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + margin: 1px 0; + padding: 0 auto; + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background-image: url(images/image.jpg); + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +#functions { + @var: 10; + color: color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 50%); + darken: darken(#ff0000, 50%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); +} + +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, @var * 2); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: @arg1 * 2px; + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: @glob + @a; +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: @a * 10; + + .innest { + width: @a; + .mix-inner(@a * 2); + } + } +} + +.class { + .mix(30); +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/benchmark/less-benchmark.js b/node_modules/grunt-contrib-less/node_modules/less/benchmark/less-benchmark.js new file mode 100644 index 000000000..ba789d52b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/benchmark/less-benchmark.js @@ -0,0 +1,46 @@ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var less = require('../lib/less'); +var file = path.join(__dirname, 'benchmark.less'); + +if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) } + +fs.readFile(file, 'utf8', function (e, data) { + var tree, css, start, end, total; + + console.log("Benchmarking...\n", path.basename(file) + " (" + + parseInt(data.length / 1024) + " KB)", ""); + + start = new(Date); + + new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) { + end = new Date(); + + total = end - start; + + console.log("Parsing: " + + total + " ms (" + + Number(1000 / total * data.length / 1024) + " KB\/s)"); + + start = new Date(); + css = tree.toCSS(); + end = new Date(); + + console.log("Generation: " + (end - start) + " ms (" + + parseInt(1000 / (end - start) * + data.length / 1024) + " KB\/s)"); + + total += end - start; + + console.log("Total: " + total + "ms (" + + Number(1000 / total * data.length / 1024) + " KB/s)"); + + if (err) { + less.writeError(err); + process.exit(3); + } + }); +}); + diff --git a/node_modules/grunt-contrib-less/node_modules/less/bin/lessc b/node_modules/grunt-contrib-less/node_modules/less/bin/lessc new file mode 100755 index 000000000..536ded870 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/bin/lessc @@ -0,0 +1,368 @@ +#!/usr/bin/env node + +var path = require('path'), + fs = require('fs'), + sys = require('util'), + os = require('os'), + mkdirp; + +var less = require('../lib/less'); +var args = process.argv.slice(1); +var options = { + depends: false, + compress: false, + cleancss: false, + max_line_len: -1, + optimization: 1, + silent: false, + verbose: false, + lint: false, + paths: [], + color: true, + strictImports: false, + insecure: false, + rootpath: '', + relativeUrls: false, + ieCompat: true, + strictMath: false, + strictUnits: false, + globalVariables: '', + modifyVariables: '' +}; +var continueProcessing = true, + currentErrorcode; + +// calling process.exit does not flush stdout always +// so use this to set the exit code +process.on('exit', function() { process.reallyExit(currentErrorcode) }); + +var checkArgFunc = function(arg, option) { + if (!option) { + console.log(arg + " option requires a parameter"); + continueProcessing = false; + return false; + } + return true; +}; + +var checkBooleanArg = function(arg) { + var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg); + if (!onOff) { + console.log(" unable to parse "+arg+" as a boolean. use one of on/t/true/y/yes/off/f/false/n/no"); + continueProcessing = false; + return false; + } + return Boolean(onOff[2]); +}; + +var parseVariableOption = function(option) { + var parts = option.split('=', 2); + return '@' + parts[0] + ': ' + parts[1] + ';\n'; +}; + +var warningMessages = ""; +var sourceMapFileInline = false; + +args = args.filter(function (arg) { + var match; + + if (match = arg.match(/^-I(.+)$/)) { + options.paths.push(match[1]); + return false; + } + + if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i)) { arg = match[1] } + else { return arg } + + switch (arg) { + case 'v': + case 'version': + console.log("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); + continueProcessing = false; + case 'verbose': + options.verbose = true; + break; + case 's': + case 'silent': + options.silent = true; + break; + case 'l': + case 'lint': + options.lint = true; + break; + case 'strict-imports': + options.strictImports = true; + break; + case 'h': + case 'help': + require('../lib/less/lessc_helper').printUsage(); + continueProcessing = false; + case 'x': + case 'compress': + options.compress = true; + break; + case 'insecure': + options.insecure = true; + break; + case 'M': + case 'depends': + options.depends = true; + break; + case 'yui-compress': + warningMessages += "yui-compress option has been removed. ignoring."; + break; + case 'clean-css': + options.cleancss = true; + break; + case 'max-line-len': + if (checkArgFunc(arg, match[2])) { + options.maxLineLen = parseInt(match[2], 10); + if (options.maxLineLen <= 0) { + options.maxLineLen = -1; + } + } + break; + case 'no-color': + options.color = false; + break; + case 'no-ie-compat': + options.ieCompat = false; + break; + case 'no-js': + options.javascriptEnabled = false; + break; + case 'include-path': + if (checkArgFunc(arg, match[2])) { + options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') + .map(function(p) { + if (p) { + return path.resolve(process.cwd(), p); + } + }); + } + break; + case 'O0': options.optimization = 0; break; + case 'O1': options.optimization = 1; break; + case 'O2': options.optimization = 2; break; + case 'line-numbers': + if (checkArgFunc(arg, match[2])) { + options.dumpLineNumbers = match[2]; + } + break; + case 'source-map': + if (!match[2]) { + options.sourceMap = true; + } else { + options.sourceMap = match[2]; + } + break; + case 'source-map-rootpath': + if (checkArgFunc(arg, match[2])) { + options.sourceMapRootpath = match[2]; + } + break; + case 'source-map-basepath': + if (checkArgFunc(arg, match[2])) { + options.sourceMapBasepath = match[2]; + } + break; + case 'source-map-map-inline': + sourceMapFileInline = true; + options.sourceMap = true; + break; + case 'source-map-less-inline': + options.outputSourceFiles = true; + break; + case 'source-map-url': + if (checkArgFunc(arg, match[2])) { + options.sourceMapURL = match[2]; + } + break; + case 'rp': + case 'rootpath': + if (checkArgFunc(arg, match[2])) { + options.rootpath = match[2].replace(/\\/g, '/'); + } + break; + case "ru": + case "relative-urls": + options.relativeUrls = true; + break; + case "sm": + case "strict-math": + if (checkArgFunc(arg, match[2])) { + options.strictMath = checkBooleanArg(match[2]); + } + break; + case "su": + case "strict-units": + if (checkArgFunc(arg, match[2])) { + options.strictUnits = checkBooleanArg(match[2]); + } + break; + case "global-var": + if (checkArgFunc(arg, match[2])) { + options.globalVariables += parseVariableOption(match[2]); + } + break; + case "modify-var": + if (checkArgFunc(arg, match[2])) { + options.modifyVariables += parseVariableOption(match[2]); + } + break; + default: + require('../lib/less/lessc_helper').printUsage(); + continueProcessing = false; + break; + } +}); + +if (!continueProcessing) { + process.reallyExit(1); +} + +var input = args[1]; +var inputbase = args[1]; +if (input && input != '-') { + input = path.resolve(process.cwd(), input); +} +var output = args[2]; +var outputbase = args[2]; +if (output) { + options.sourceMapOutputFilename = output; + output = path.resolve(process.cwd(), output); + if (warningMessages) { + console.log(warningMessages); + } +} + +options.sourceMapBasepath = options.sourceMapBasepath || (input ? path.dirname(input) : process.cwd()); + +if (options.sourceMap === true) { + if (!output && !sourceMapFileInline) { + console.log("the sourcemap option only has an optional filename if the css filename is given"); + return; + } + options.sourceMapFullFilename = options.sourceMapOutputFilename + ".map"; + options.sourceMap = path.basename(options.sourceMapFullFilename); +} + +if (options.cleancss && options.sourceMap) { + console.log("the sourcemap option is not compatible with sourcemap support at the moment. See Issue #1656"); + return; +} + +if (! input) { + console.log("lessc: no input files"); + console.log(""); + require('../lib/less/lessc_helper').printUsage(); + currentErrorcode = 1; + return; +} + +var ensureDirectory = function (filepath) { + var dir = path.dirname(filepath), + cmd, + existsSync = fs.existsSync || path.existsSync; + if (!existsSync(dir)) { + if (mkdirp === undefined) { + try {mkdirp = require('mkdirp');} + catch(e) { mkdirp = null; } + } + cmd = mkdirp && mkdirp.sync || fs.mkdirSync; + cmd(dir); + } +}; + +if (options.depends) { + if (!outputbase) { + sys.print("option --depends requires an output path to be specified"); + return; + } + sys.print(outputbase + ": "); +} + +if (!sourceMapFileInline) { + var writeSourceMap = function(output) { + var filename = options.sourceMapFullFilename || options.sourceMap; + ensureDirectory(filename); + fs.writeFileSync(filename, output, 'utf8'); + }; +} + +var parseLessFile = function (e, data) { + if (e) { + console.log("lessc: " + e.message); + currentErrorcode = 1; + return; + } + + data = options.globalVariables + data + options.modifyVariables; + + options.paths = [path.dirname(input)].concat(options.paths); + options.filename = input; + + var parser = new(less.Parser)(options); + parser.parse(data, function (err, tree) { + if (err) { + less.writeError(err, options); + currentErrorcode = 1; + return; + } else if (options.depends) { + for(var file in parser.imports.files) { + sys.print(file + " ") + } + sys.print("\n"); + } else if(!options.lint) { + try { + var css = tree.toCSS({ + silent: options.silent, + verbose: options.verbose, + ieCompat: options.ieCompat, + compress: options.compress, + cleancss: options.cleancss, + sourceMap: Boolean(options.sourceMap), + sourceMapFilename: options.sourceMap, + sourceMapURL: options.sourceMapURL, + sourceMapOutputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath || "", + outputSourceFiles: options.outputSourceFiles, + writeSourceMap: writeSourceMap, + maxLineLen: options.maxLineLen, + strictMath: options.strictMath, + strictUnits: options.strictUnits + }); + if (output) { + ensureDirectory(output); + fs.writeFileSync(output, css, 'utf8'); + if (options.verbose) { + console.log('lessc: wrote ' + output); + } + } else { + sys.print(css); + } + } catch (e) { + less.writeError(e, options); + currentErrorcode = 2; + return; + } + } + }); +}; + +if (input != '-') { + fs.readFile(input, 'utf8', parseLessFile); +} else { + process.stdin.resume(); + process.stdin.setEncoding('utf8'); + + var buffer = ''; + process.stdin.on('data', function(data) { + buffer += data; + }); + + process.stdin.on('end', function() { + parseLessFile(false, buffer); + }); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/bower.json b/node_modules/grunt-contrib-less/node_modules/less/bower.json new file mode 100644 index 000000000..482862ddb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/bower.json @@ -0,0 +1,18 @@ +{ + "name": "less", + "version": "1.5.0", + "main": "./dist/less-1.5.0.js", + "ignore": [ + "**/.*", + "benchmark", + "bin", + "build", + "lib", + "test", + "*.md", + "LICENSE", + "Gruntfile.js", + "package.json", + "bower.json" + ] +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/README.md b/node_modules/grunt-contrib-less/node_modules/less/build/README.md new file mode 100644 index 000000000..f2d5359af --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/README.md @@ -0,0 +1,335 @@ +# [Less.js v<%= pkg.version %>](http://lesscss.org) + +> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org). + +This is the JavaScript, and now official, stable version of LESS. + + +## Getting Started + +Options for adding Less.js to your project: + +* Install with [NPM](https://npmjs.org/): `npm install less` +* [Download the latest release][download] +* Clone the repo: `git clone git://github.com/less/less.js.git` + + + +## Feature Highlights +LESS extends CSS with dynamic features such as: + +* [nesting](#nesting) +* [variables](#variables) +* [operations](#operations) +* [mixins](#mixins) +* [extend](#extend) (selector inheritance) + +To learn about the many other features Less.js has to offer please visit [http://lesscss.org](http://lesscss.org) and [the Less.js wiki][wiki] + + +### Examples +#### nesting +Take advantage of nesting to make code more readable and maintainable. This: + +```less +.nav > li > a { + border: 1px solid #f5f5f5; + &:hover { + border-color: #ddd; + } +} +``` + +renders to: + +```css +.nav > li > a { + border: 1px solid #f5f5f5; +} +.nav > li > a:hover { + border-color: #ddd; +} +``` + + +#### variables +Updated commonly used values from a single location. + +```less +// Variables ("inline" comments like this can be used) +@link-color: #428bca; // appears as "sea blue" + +/* Or "block comments" that span + multiple lines, like this */ +a { + color: @link-color; // use the variable in styles +} +``` + +Variables can also be used in `@import` statements, URLs, selector names, and more. + + + +#### operations +Continuing with the same example above, we can use our variables even easier to maintain with _operations_, which enables the use of addition, subraction, multiplication and division in your styles: + +```less +// Variables +@link-color: #428bca; +@link-color-hover: darken(@link-color, 10%); + +// Styles +a { + color: @link-color; +} +a:hover { + color: @link-color-hover; +} +``` +renders to: + +```css +a { + color: #428bca; +} +a:hover { + color: #3071a9; +} +``` + +#### mixins +##### "implicit" mixins +Mixins enable you to apply the styles of one selector inside another selector like this: + +```less +// Any "regular" class... +.link { + color: @link-color; +} +a { + font-weight: bold; + .link; // ...can be used as an "implicit" mixin +} +``` + +renders to: + +```css +.link { + color: #428bca; +} +a { + font-weight: bold; + color: #428bca; +} +``` + +So any selector can be an "implicit mixin". We'll show you a DRYer way to do this below. + + + +##### parametric mixins +Mixins can also accept parameters: + +```less +// Transition mixin +.transition(@transition) { + -webkit-transition: @transition; + -moz-transition: @transition; + -o-transition: @transition; + transition: @transition; +} +``` + +used like this: + +```less +a { + font-weight: bold; + color: @link-color; + .transition(color .2s ease-in-out); + // Hover state + &:hover { + color: @link-color-hover; + } +} +``` + +renders to: + +```css +a { + font-weight: bold; + color: #428bca; + -webkit-transition: color 0.2s ease-in-out; + -moz-transition: color 0.2s ease-in-out; + -o-transition: color 0.2s ease-in-out; + transition: color 0.2s ease-in-out; +} +a:hover { + color: #3071a9; +} +``` + + +#### extend +The `extend` feature can be thought of as the _inverse_ of mixins. It accomplishes the goal of "borrowing styles", but rather than copying all the rules of _Selector A_ over to _Selector B_, `extend` copies the name of the _inheriting selector_ (_Selector B_) over to the _extending selector_ (_Selector A_). So continuing with the example used for [mixins](#mixins) above, extend works like this: + +```less +.link { + color: @link-color; +} +a:extend(.link) { + font-weight: bold; +} +// Can also be written as +a { + &:extend(.link); + font-weight: bold; +} +``` + +renders to: + +```css +.link, a { + color: #428bca; +} +``` + +## Usage + +### Compiling and Parsing +Invoke the compiler from node: + +```javascript +var less = require('less'); + +less.render('.class { width: (1 + 1) }', function (e, css) { + console.log(css); +}); +``` + +Outputs: + +```css +.class { + width: 2; +} +``` + +You may also manually invoke the parser and compiler: + +```javascript +var parser = new(less.Parser); + +parser.parse('.class { width: (1 + 1) }', function (err, tree) { + if (err) { return console.error(err) } + console.log(tree.toCSS()); +}); +``` + + +### Configuration +You may also pass options to the compiler: + +```javascript +var parser = new(less.Parser)({ + paths: ['.', './src/less'], // Specify search paths for @import directives + filename: 'style.less' // Specify a filename, for better error messages +}); + +parser.parse('.class { width: (1 + 1) }', function (e, tree) { + tree.toCSS({ compress: true }); // Minify CSS output +}); +``` + +## More information + +For general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org) or [the less wiki][wiki]. + +Here are other resources for using Less.js: + +* [stackoverflow.com][so] is a great place to get answers about Less. +* [node.js tools](https://github.com/less/less.js/wiki/Converting-LESS-to-CSS) for converting Less to CSS +* [GUI compilers for Less](https://github.com/less/less.js/wiki/GUI-compilers-that-use-LESS.js) +* [Less.js Issues][issues] for reporting bugs + + + +## Contributing +Please read [CONTRIBUTING.md](./CONTRIBUTING.md). Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). + +### Reporting Issues + +Before opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/). After that if you find a bug or would like to make feature request, [please open a new issue][issues]. + + + +### Development + +#### Install Less.js + +Start by either [downloading this project][download] manually, or in the command line: + +```shell +git clone https://github.com/less/less.js.git "less" +``` +and then `cd less`. + + +#### Install dependencies + +To install all the dependencies for less development, run: + +```shell +npm install +``` + +If you haven't run grunt before, install grunt-cli globally so you can just run `grunt` + +```shell +npm install grunt-cli -g +``` + +You should now be able to build Less.js, run tests, benchmarking, and other tasks listed in the Gruntfile. + +## Using Less.js Grunt + +Tests, benchmarking and building is done using Grunt `<%= pkg.devDependencies.grunt %>`. If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to install and use Grunt plugins, which are necessary for development with Less.js. + +The Less.js [Gruntfile](Gruntfile.js) is configured with the following "convenience tasks" : + +#### test - `grunt` +Runs jshint, nodeunit and headless jasmine tests using [phantomjs](http://code.google.com/p/phantomjs/). You must have phantomjs installed for the jasmine tests to run. + +#### test - `grunt benchmark` +Runs the benchmark suite. + +#### build for testing browser - 'grunt browser' +This builds less.js and puts it in 'test/browser/less.js' + +#### build - `grunt stable | grunt beta | grunt alpha` +Builds Less.js from from the `/lib/less` source files. This is done by the developer releasing a new release, do not do this if you are creating a pull request. + +#### readme - `grunt readme` +Build the README file from [a template](build/README.md) to ensure that metadata is up-to-date and (more likely to be) correct. + +Please review the [Gruntfile](Gruntfile.js) to become acquainted with the other available tasks. + +**Please note** that if you have any issues installing dependencies or running any of the Gruntfile commands, please make sure to uninstall any previous versions, both in the local node_modules directory, and clear your global npm cache, and then try running `npm install` again. After that if you still have issues, please let us know about it so we can help. + + +## Release History +See the [changelog](CHANGELOG) + +## [License](LICENSE) + +Copyright (c) 2009-<%= grunt.template.today("yyyy") %> [Alexis Sellier](http://cloudhead.io/) & The Core Less Team +Licensed under the [Apache License](LICENSE). + + +[so]: http://stackoverflow.com/questions/tagged/twitter-bootstrap+less "StackOverflow.com" +[issues]: https://github.com/less/less.js/issues "GitHub Issues for Less.js" +[wiki]: https://github.com/less/less.js/wiki "The official wiki for Less.js" +[download]: https://github.com/less/less.js/zipball/master "Download Less.js" \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/amd.js b/node_modules/grunt-contrib-less/node_modules/less/build/amd.js new file mode 100644 index 000000000..7d7e33c55 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/amd.js @@ -0,0 +1,6 @@ +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/browser-header.js b/node_modules/grunt-contrib-less/node_modules/less/build/browser-header.js new file mode 100644 index 000000000..eaff5bfc4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/browser-header.js @@ -0,0 +1,4 @@ +if (typeof(window.less) === 'undefined' || typeof(window.less.nodeType) !== 'undefined') { window.less = {}; } +less = window.less; +tree = window.less.tree = {}; +less.mode = 'browser'; diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/build.yml b/node_modules/grunt-contrib-less/node_modules/less/build/build.yml new file mode 100644 index 000000000..3c5fe5869 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/build.yml @@ -0,0 +1,147 @@ +### +# NOTICE: +# this file is specifically for controlling +# paths for Less.js source files, as well as +# the order in which source files are +# concatenated. +# +# Please do not add paths for anything else +# to this file. All other paths for testing, +# benchmarking and so on should be controlled +# in the Gruntfile. +### + +# Less.js Lib +lib: lib/less + + +# ================================= +# General +# ================================= +prepend: + browser: ['build/require.js', 'build/browser-header.js'] + rhino: build/require-rhino.js + +append: + amd: build/amd.js + browser: <%= build.lib %>/browser.js + rhino: <%= build.lib %>/rhino.js + + +# ================================= +# Core less files +# ================================= + +# <%= build.less.* %> +less: + parser : <%= build.lib %>/parser.js + functions : <%= build.lib %>/functions.js + colors : <%= build.lib %>/colors.js + tree : <%= build.lib %>/tree.js + treedir : <%= build.lib %>/tree/*.js # glob all files in ./lib/less/tree directory + env : <%= build.lib %>/env.js + visitor : <%= build.lib %>/visitor.js + import_visitor : <%= build.lib %>/import-visitor.js + join : <%= build.lib %>/join-selector-visitor.js + to_css_visitor : <%= build.lib %>/to-css-visitor.js + extend_visitor : <%= build.lib %>/extend-visitor.js + browser : <%= build.lib %>/browser.js + source_map_output: <%= build.lib %>/source-map-output.js + + +# ================================= +# Browser build +# ================================= + +# <%= build.browser %> +browser: + + # prepend utils + - <%= build.prepend.browser %> + + # core + - <%= build.less.parser %> + - <%= build.less.functions %> + - <%= build.less.colors %> + - <%= build.less.tree %> + - <%= build.less.treedir %> # glob all files + - <%= build.less.env %> + - <%= build.less.visitor %> + - <%= build.less.import_visitor %> + - <%= build.less.join %> + - <%= build.less.to_css_visitor %> + - <%= build.less.extend_visitor %> + - <%= build.less.source_map_output %> + + # append browser-specific code + - <%= build.append.browser %> + - <%= build.append.amd %> + + +# ================================= +# Rhino build +# ================================= + +# <%= build.rhino %> +rhino: + # prepend utils + - <%= build.prepend.rhino %> + + # core + - <%= build.less.parser %> + - <%= build.less.env %> + - <%= build.less.visitor %> + - <%= build.less.import_visitor %> + - <%= build.less.join %> + - <%= build.less.to_css_visitor %> + - <%= build.less.extend_visitor %> + - <%= build.less.functions %> + - <%= build.less.colors %> + - <%= build.less.tree %> + - <%= build.less.treedir %> # glob all files + - <%= build.less.source_map_output %> + + # append rhino-specific code + - <%= build.append.rhino %> + + +# ================================= +# Tree files +# ================================= + +# <%= build.tree %> +# Technically listing the array out this way isn't +# necessary since we can glob the files in alphabetical +# order anyway. But this gives you control over the order +# the files are used, and allows targeting of individual +# files directly in the Gruntfile. But be we can just +# remove this if files can be concatenated in any order. +tree: + - <%= build.lib %>/tree/alpha.js + - <%= build.lib %>/tree/anonymous.js + - <%= build.lib %>/tree/assignment.js + - <%= build.lib %>/tree/call.js + - <%= build.lib %>/tree/color.js + - <%= build.lib %>/tree/comment.js + - <%= build.lib %>/tree/condition.js + - <%= build.lib %>/tree/dimension.js + - <%= build.lib %>/tree/directive.js + - <%= build.lib %>/tree/element.js + - <%= build.lib %>/tree/expression.js + - <%= build.lib %>/tree/extend.js + - <%= build.lib %>/tree/import.js + - <%= build.lib %>/tree/javascript.js + - <%= build.lib %>/tree/keyword.js + - <%= build.lib %>/tree/media.js + - <%= build.lib %>/tree/mixin.js + - <%= build.lib %>/tree/negative.js + - <%= build.lib %>/tree/operation.js + - <%= build.lib %>/tree/paren.js + - <%= build.lib %>/tree/quoted.js + - <%= build.lib %>/tree/rule.js + - <%= build.lib %>/tree/ruleset.js + - <%= build.lib %>/tree/selector.js + - <%= build.lib %>/tree/unicode-descriptor.js + - <%= build.lib %>/tree/url.js + - <%= build.lib %>/tree/value.js + - <%= build.lib %>/tree/variable.js diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/require-rhino.js b/node_modules/grunt-contrib-less/node_modules/less/build/require-rhino.js new file mode 100644 index 000000000..02bc83ce1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/require-rhino.js @@ -0,0 +1,7 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/require.js b/node_modules/grunt-contrib-less/node_modules/less/build/require.js new file mode 100644 index 000000000..4d5b1720f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/require.js @@ -0,0 +1,7 @@ +// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/rhino-header.js b/node_modules/grunt-contrib-less/node_modules/less/build/rhino-header.js new file mode 100644 index 000000000..891f09437 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/rhino-header.js @@ -0,0 +1,4 @@ +if (typeof(window) === 'undefined') { less = {} } +else { less = window.less = {} } +tree = less.tree = {}; +less.mode = 'rhino'; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/build/tasks/.gitkeep b/node_modules/grunt-contrib-less/node_modules/less/build/tasks/.gitkeep new file mode 100644 index 000000000..9a69c4cb6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/build/tasks/.gitkeep @@ -0,0 +1 @@ +# Reserved for specialized Less.js tasks. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.js new file mode 100644 index 000000000..487c06acd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.js @@ -0,0 +1,2695 @@ +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function (window, undefined) { +// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else { + return this.value[0].eval(env); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + toCSS: function () { + if (this.escaped) { + return this.evaluated; + } else { + return JSON.stringify(this.evaluated); + } + }, + eval: function (env) { + var result, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name).eval(env).value; + }); + + expression = new(Function)('return (' + expression + ')'); + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + this.evaluated = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + return this; + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(this.arguments, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + this.value = this.value.replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name).eval(env).value; + }).replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, this.index, true).eval(env).toCSS(); + }); + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.min.js new file mode 100644 index 000000000..ede454e10 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.0.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value[0].eval(b)},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(this.arguments, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + this.value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + return new(tree.Variable)('@' + name, that.index).eval(env).value; + }); + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.1.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.1.min.js new file mode 100644 index 000000000..c204123ec --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.1.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){for(var f=0;f0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree" +)),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args) { + this.name = name; + this.args = args; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + return tree.functions[this.name].apply(tree.functions, args); + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.2.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.2.min.js new file mode 100644 index 000000000..9b2fc8a43 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.2.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){ +if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '&' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value.trim(); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + for (var s = 0; s < this.selectors.length; s++) { + for (var c = 0; c < context.length; c++) { + paths.push(context[c].concat([this.selectors[s]])); + } + } + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.3.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.3.min.js new file mode 100644 index 000000000..6e4d5cff5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.3.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this +.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + less = exports, + tree = require('less/tree'); +} else { + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^(?:\d*\.)?\d+%/); + + if (e) { return new(tree.Element)(c, e) } + + if (c.value && c.value[0] === '&') { + return new(tree.Element)(c, null); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#:% \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value[0] === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + styles[i].type = 'text/css'; + styles[i].innerHTML = tree.toCSS(); + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.4.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.4.min.js new file mode 100644 index 000000000..182b526fb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.4.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.4 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.4 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function u(a,b){var c="less-error-message:"+o(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function s(a){return a&&a.parentNode.removeChild(a)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){t("browser doesn't support AJAX.");return null}}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function p(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||o(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(h){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function o(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function n(b,c,e,f){var h=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=g&&g.getItem(i),k=g&&g.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=h.slice(0,h.lastIndexOf("/")+1)+i),q(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())p(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return u(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),s(document.getElementById("less-error-message:"+o(i)))}catch(a){u(a,i)}})}catch(h){u(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function m(a,b){for(var c=0;c>>0;for(var d=0;d>>0,c=Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/)||s(/^(?:\d*\.)?\d+%/);if(a)return new e.Element(c,a);if(c.value&&c.value[0]==="&")return new e.Element(c,null)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#:% \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs +.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (less.mode === 'browser' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + try { + style.innerHTML = css; + } catch (_) { + style.styleSheets.cssText = css; + } + style.type = 'text/css'; + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.5.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.5.min.js new file mode 100644 index 000000000..49949fbea --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.5.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.1.5 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;ck&&(j[f]=j[f].slice(c-k),k=c)}function s(a){var d,e,g,h,i,m,n,o;if(a instanceof Function)return a.call(l.parsers);if(typeof a=="string")d=b.charAt(c)===a?a:null,g=1,r();else{r();if(d=a.exec(j[f]))g=d[0].length;else return null}if(d){o=c+=g,m=c+j[f].length-g;while(c0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)!=="/")return;if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=='"'&&b.charAt(d)!=="'")return;f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)},keyword:function(){var a;if(a=s(/^[_A-Za-z-][_A-Za-z0-9-]*/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!(a=/^([\w-]+|%)\(/.exec(j[f])))return;a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)!=="u"||!s(/^url\(/))return;a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(d>57||d<45||d===47)return;if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)!=="`")return;f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!t(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i!=="."&&i!=="#")return;while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d,c)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,d=[],f,g,h,i;if(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/))return;if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!s(/^\(opacity=/i))return;if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,d;d=s(this.combinator),a=s(/^(?:\d+\.\d+|\d+)%/)||s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(d,a,c);if(d.value&&d.value.charAt(0)==="&")return new e.Element(d,null,c)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d==="&"){a="&",c++,b.charAt(c)===" "&&(a="& ");while(b.charAt(c)===" ")c++;return new e.Combinator(a)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!s("["))return;if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,f;p();while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g==="."||g==="#"||g==="&")return;if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)!=="@")return;if(d=s(this["import"]))return d;if(a=s(/^@media|@page/)||s(/^@(?:-webkit-|-moz-)?keyframes/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(a.value=b[0]+(a.value.charAt(0)==="/"?a.value.slice(1):a.value)),this.value=a,this.paths=b)},a.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(b){return this.attrs?this:new a.URL(this.value.eval(b),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k) + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/) || $('keyframes')) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + try { + style.innerHTML = css; + } catch (_) { + style.styleSheets.cssText = css; + } + style.type = 'text/css'; + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.6.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.6.min.js new file mode 100644 index 000000000..a30623b99 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.1.6.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.1.6 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),m=new e.Ruleset([],t(this.parsers.primary)),m.root=!0,m.toCSS=function(f){var g,h,i;return function(i,j){function p(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var k=[];i=i||{},typeof j=="object"&&!Array.isArray(j)&&(j=Object.keys(j).map(function(a){var b=j[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),k=[new e.Ruleset(null,j)]);try{var l=f.call(this,{frames:k}).toCSS([],{compress:i.compress||!1})}catch(m){h=b.split("\n"),g=p(m.index);for(var n=m.index,o=-1;n>=0&&b.charAt(n)!=="\n";n--)o++;throw{type:m.type,message:m.message,filename:a.filename,index:m.index,line:typeof g=="number"?g+1:null,callLine:m.call&&p(m.call)+1,callExtract:h[p(m.call)],stack:m.stack,column:o,extract:[h[g-1],h[g],h[g+1]]}}return i.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(l):i.compress?l.replace(/(\s)+/g,"$1"):l}}(m.eval);if(f=0&&b.charAt(x)!=="\n";x--)y++;w={name:"ParseError",message:"Syntax Error on line "+r,index:f,filename:a.filename,line:r,column:y,extract:[s[r-2],s[r-1],s[r]]}}this.imports.queue.length>0?o=function(){i(w,m)}:i(w,m)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var a,b,c=f;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;a=a[1].toLowerCase();if(a==="url")return null;f+=a.length;if(a==="alpha")return t(this.alpha);t("("),b=t(this.entities.arguments);if(!t(")"))return;if(a)return new e.Call(a,b,c)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!t(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=f;if(b.charAt(f)==="@"&&(a=t(/^@@?[\w-]+/)))return new e.Variable(a,c)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!u(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,g,h=f,i=b.charAt(f);if(i!=="."&&i!=="#")return;while(c=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(d,c,f)),d=t(">");t("(")&&(g=t(this.entities.arguments))&&t(")");if(a.length>0&&(t(";")||u("}")))return new e.mixin.Call(a,g,h)},definition:function(){var a,c=[],d,g,h,i;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||u(/^[^{]*(;|})/))return;if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)){if(h instanceof e.Variable)if(t(":"))if(i=t(this.expression))c.push({name:h.name,value:i});else throw new Error("Expected value");else c.push({name:h.name});else c.push({value:h});if(!t(","))break}if(!t(")"))throw new Error("Expected )");g=t(this.block);if(g)return new e.mixin.Definition(a,c,g)}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||u("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable)){if(!t(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/);if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}if(c===":"&&b.charAt(f+1)===":"){f+=2;while(b.charAt(f)===" ")f++;return new e.Combinator("::")}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var a=[],b,c,d;q();while(b=t(this.selector)){a.push(b),t(this.comment);if(!t(","))break;t(this.comment)}if(a.length>0&&(c=t(this.block)))return new e.Ruleset(a,c);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))&&t(";"))return new e.Import(a,p)},directive:function(){var a,c,d,g;if(b.charAt(f)!=="@")return;if(c=t(this["import"]))return c;if(a=t(/^@media|@page/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)||t("keyframes")){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!u(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("../tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){return this.ruleset?(this.ruleset.root=!0,this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c?c.trim():"",this.index=d},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;ee.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),c("./tree").find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c){a&&p(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getLocation(index) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: index ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var lines = input.split('\n'), + loc = getLocation(e.index), + line = loc.line, + col = loc.column; + + this.type = e.type || 'SyntaxError'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call) + 1); + this.callExtract = lines[getLocation(e.call)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if (parser.imports.error) { throw parser.imports.error } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features) { + var that = this; + + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (root, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (root, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(root, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + + var template = ['
    ', + '
  • {0}
  • ', + '
  • {current}
  • ', + '
  • {2}
  • ', + '
'].join('\n'); + + var elem = document.createElement('div'), timer, content; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

' + (e.message || 'There is an error in your .less file') + + '

' + '

' + href + " "; + + if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

' + + template.replace(/\[(-?\d)\]/g, function (_, i) { + return (parseInt(e.line) + parseInt(i)) || ''; + }).replace(/\{(\d)\}/g, function (_, i) { + return e.extract[parseInt(i)] || ''; + }).replace(/\{current\}/, e.extract[1].slice(0, e.column) + '' + + e.extract[1].slice(e.column) + ''); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #ee4444;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.ctx {', + 'color: #dd4444;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.0.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.0.min.js new file mode 100644 index 000000000..84e90475a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.0.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e=["
    ",'
  • {0}
  • ',"
  • {current}
  • ",'
  • {2}
  • ',"
"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="

"+(a.message||"There is an error in your .less file")+"

"+'

'+b+" ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":

"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+''+a.extract[1].slice(a.column)+"")),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cm&&(l[h]=l[h].slice(g-m),m=g)}function v(a){var c,d,e,f,i,j,k,o;if(a instanceof Function)return a.call(n.parsers);if(typeof a=="string")c=b.charAt(g)===a?a:null,e=1,u();else{u();if(c=a.exec(l[h]))e=c[0].length;else return null}if(c){o=g+=e,j=g+l[h].length-e;while(g=0&&b.charAt(c)!=="\n";c--)d++;return{line:a?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,c){var d=b.split("\n"),e=z(a.index),f=e.line,g=e.column;this.type=a.type||"SyntaxError",this.message=a.message,this.filename=a.filename||c.filename,this.index=a.index,this.line=typeof f=="number"?f+1:null,this.callLine=a.call&&z(a.call)+1,this.callExtract=d[z(a.call)],this.stack=a.stack,this.column=g,this.extract=[d[f-1],d[f],d[f+1]]}var b,g,h,i,j,k,l,m,n,o=this,q=function(){},r=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&q()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,n={imports:r,parse:function(e,i){var j,o,p,r,s,t,u=[],w,x=null;g=h=m=k=0,l=[],b=e.replace(/\r\n/g,"\n"),l=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],v(this.parsers.primary)),j.root=!0}catch(y){return i(new A(y,a))}j.toCSS=function(b){var e,g,h;return function(e,g){var h=[];e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var i=b.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(j){throw new A(j,a)}if(n.imports.error)throw n.imports.error;return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(i):e.compress?i.replace(/(\s)+/g,"$1"):i}}(j.eval);if(g=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:g,filename:a.filename,line:s,column:B,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?q=function(){i(x,j)}:i(x,j)},parsers:{primary:function(){var a,b=[];while((a=v(this.mixin.definition)||v(this.rule)||v(this.ruleset)||v(this.mixin.call)||v(this.comment)||v(this.directive))||v(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(g)!=="/")return;if(b.charAt(g+1)==="/")return new f.Comment(v(/^\/\/.*/),!0);if(a=v(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&v("~");if(a=v(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=v(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,b,c=g;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(l[h])))return;a=a[1].toLowerCase();if(a==="url")return null;g+=a.length;if(a==="alpha")return v(this.alpha);v("("),b=v(this.entities.arguments);if(!v(")"))return;if(a)return new f.Call(a,b,c)},arguments:function(){var a=[],b;while(b=v(this.entities.assignment)||v(this.expression)){a.push(b);if(!v(","))break}return a},literal:function(){return v(this.entities.dimension)||v(this.entities.color)||v(this.entities.quoted)},assignment:function(){var a,b;if((a=v(/^\w+(?=\s?=)/i))&&v("=")&&(b=v(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(b.charAt(g)!=="u"||!v(/^url\(/))return;return a=v(this.entities.quoted)||v(this.entities.variable)||v(this.entities.dataURI)||v(/^[-\w%@$\/.&=:;#+?~]+/)||"",w(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),r.paths)},dataURI:function(){var a;if(v(/^data:/)){a={},a.mime=v(/^[^\/]+\/[^,;)]+/)||"",a.charset=v(/^;\s*charset=[^,;)]+/)||"",a.base64=v(/^;\s*base64/)||"",a.data=v(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=g;if(b.charAt(g)==="@"&&(a=v(/^@@?[\w-]+/)))return new f.Variable(a,c)},color:function(){var a;if(b.charAt(g)==="#"&&(a=v(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(g);if(c>57||c<45||c===47)return;if(a=v(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,c=g,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&v("~");if(a=v(/^`([^`]*)`/))return new f.JavaScript(a[1],g,d)}},variable:function(){var a;if(b.charAt(g)==="@"&&(a=v(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!y(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=v(this.entity))&&v("/")&&(b=v(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,h=g,i=b.charAt(g),j=!1;if(i!=="."&&i!=="#")return;while(c=v(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,g)),d=v(">");v("(")&&(e=v(this.entities.arguments))&&v(")"),v(this.important)&&(j=!0);if(a.length>0&&(v(";")||y("}")))return new f.mixin.Call(a,e,h,j)},definition:function(){var a,c=[],d,e,h,i,j;if(b.charAt(g)!=="."&&b.charAt(g)!=="#"||y(/^[^{]*(;|})/))return;s();if(d=v(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];while(h=v(this.entities.variable)||v(this.entities.literal)||v(this.entities.keyword)){h instanceof f.Variable?v(":")?(i=w(this.expression,"expected expression"),c.push({name:h.name,value:i})):c.push({name:h.name}):c.push({value:h});if(!v(","))break}w(")"),v(/^when/)&&(j=w(this.conditions,"expected condition")),e=v(this.block);if(e)return new f.mixin.Definition(a,c,e,j);t()}}},entity:function(){return v(this.entities.literal)||v(this.entities.variable)||v(this.entities.url)||v(this.entities.call)||v(this.entities.keyword)||v(this.entities.javascript)||v(this.comment)},end:function(){return v(";")||y("}")},alpha:function(){var a;if(!v(/^\(opacity=/i))return;if(a=v(/^\d+/)||v(this.entities.variable))return w(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=v(this.combinator),a=v(/^(?:\d+\.\d+|\d+)%/)||v(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||v("*")||v(this.attribute)||v(/^\([^)@]+\)/),a||v("(")&&(d=v(this.entities.variable))&&v(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,g);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,g)},combinator:function(){var a,c=b.charAt(g);if(c===">"||c==="+"||c==="~"){g++;while(b.charAt(g)===" ")g++;return new f.Combinator(c)}if(c==="&"){a="&",g++,b.charAt(g)===" "&&(a="& ");while(b.charAt(g)===" ")g++;return new f.Combinator(a)}if(c===":"&&b.charAt(g+1)===":"){g+=2;while(b.charAt(g)===" ")g++;return new f.Combinator("::")}return b.charAt(g-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,c,d=[],e,h;while(c=v(this.element)){e=b.charAt(g),d.push(c);if(e==="{"||e==="}"||e===";"||e===",")break}if(d.length>0)return new f.Selector(d)},tag:function(){return v(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||v("*")},attribute:function(){var a="",b,c,d;if(!v("["))return;if(b=v(/^[a-zA-Z-]+/)||v(this.entities.quoted))(d=v(/^[|~*$^]?=/))&&(c=v(this.entities.quoted)||v(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!v("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(v("{")&&(a=v(this.primary))&&v("}"))return a},ruleset:function(){var a=[],b,c,d;s();while(b=v(this.selector)){a.push(b),v(this.comment);if(!v(","))break;v(this.comment)}if(a.length>0&&(c=v(this.block)))return new f.Ruleset(a,c);k=g,t()},rule:function(){var a,c,d=b.charAt(g),e,i;s();if(d==="."||d==="#"||d==="&")return;if(a=v(this.variable)||v(this.property)){a.charAt(0)!="@"&&(i=/^([^@+\/'"*`(;{}-]*);/.exec(l[h]))?(g+=i[0].length-1,c=new f.Anonymous(i[1])):a==="font"?c=v(this.font):c=v(this.value),e=v(this.important);if(c&&v(this.end))return new f.Rule(a,c,e,j);k=g,t()}},"import":function(){var a,b;if(v(/^@import\s+/)&&(a=v(this.entities.quoted)||v(this.entities.url))){b=v(this.mediaFeatures);if(v(";"))return new f.Import(a,r,b)}},mediaFeature:function(){var a=[];do if(e=v(this.entities.keyword))a.push(e);else if(v("(")){p=v(this.property),e=v(this.entity);if(!v(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,g,!0)));else if(e)a.push(new f.Paren(e));else return null}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=v(this.mediaFeature)){b.push(a);if(!v(","))break}return b.length>0?b:null},media:function(){var a;if(v(/^@media/)){a=v(this.mediaFeatures);if(rules=v(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,c,d,e,h,i;if(b.charAt(g)!=="@")return;if(c=v(this["import"])||v(this.media))return c;if(a=v(/^@page|@keyframes/)||v(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){e=(v(/^[^{]+/)||"").trim();if(d=v(this.block))return new f.Directive(a+" "+e,d)}else if(a=v(/^@[-a-z]+/))if(a==="@font-face"){if(d=v(this.block))return new f.Directive(a,d)}else if((c=v(this.entity))&&v(";"))return new f.Directive(a,c)},font:function(){var a=[],b=[],c,d,e,g;while(g=v(this.shorthand)||v(this.entity))b.push(g);a.push(new f.Expression(b));if(v(","))while(g=v(this.expression)){a.push(g);if(!v(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=v(this.expression)){b.push(a);if(!v(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(b.charAt(g)==="!")return v(/^! *important/)},sub:function(){var a;if(v("(")&&(a=v(this.expression))&&v(")"))return a},multiplication:function(){var a,b,c,d;if(a=v(this.operand)){while(!y(/^\/\*/)&&(c=v("/")||v("*"))&&(b=v(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,e;if(a=v(this.multiplication)){while((d=v(/^[-+]\s+/)||b.charAt(g-1)!=" "&&(v("+")||v("-")))&&(c=v(this.multiplication)))e=new f.Operation(d,[e||a,c]);return e||a}},conditions:function(){var a,b,c=g,d;if(a=v(this.condition)){while(v(",")&&(b=v(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=g,h=!1;v(/^not/)&&(h=!0),w("(");if(a=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))return(d=v(/^(?:>=|=<|[<=>])/))?(b=v(this.addition)||v(this.entities.keyword)||v(this.entities.quoted))?c=new f.Condition(d,a,b,e,h):x("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,h),w(")"),v(/^and/)?new f.Condition("and",c,v(this.condition)):c},operand:function(){var a,c=b.charAt(g+1);b.charAt(g)==="-"&&(c==="@"||c==="(")&&(a=v("-"));var d=v(this.sub)||v(this.entities.dimension)||v(this.entities.color)||v(this.entities.variable)||v(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=v(this.addition)||v(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=v(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d){var e=this;this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(a,b){e.root=b})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b){this.name=a,this.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&r(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input) + 1); + this.callExtract = lines[getLocation(e.call, input)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.1.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.1.min.js new file mode 100644 index 000000000..89b76377c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.1.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&B(a.call,c)+1,this.callExtract=g[B(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return a.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function basename(pathname) { + if (less.mode === 'node') { + return require('path').basename(pathname); + } else { + return pathname.match(/[^\/]+$/)[0]; + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[basename(e.filename)]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input) + 1); + this.callExtract = lines[getLocation(e.call, input)]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)\\]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var f, features = []; + while (f = $(this.mediaFeature)) { + features.push(f); + if (! $(',')) { break } + } + return features.length > 0 ? features : null; + }, + + media: function () { + var features; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Directive)('@media', rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + this.features = features && new(tree.Value)(features); + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.ruleset) { + this.ruleset.root = true; + return this.name + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + this.features = this.features && this.features.eval(env); + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []); + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0)); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join( env.compress ? ',' : ',\n'); + + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.2.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.2.min.js new file mode 100644 index 000000000..55042ecb8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.2.2.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.2.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cn&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function D(a,b){var c=B(a,b),d=C(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&C(a.call,c)+1,this.callExtract=g[C(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)\\]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=a[0],k;for(var l=0,m,n;l0&&(x=new D({index:l,type:"Parse",message:"missing closing `}`",filename:b.filename},b)),a.map(function(a){return a.join("")})}([[]]);if(x)return e(x);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new D(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new D(k,b)}if(i=o.imports.error)throw i instanceof D?i:new D(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + callback(e, root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function basename(pathname) { + if (less.mode === 'node') { + return require('path').basename(pathname); + } else { + return pathname.match(/[^\/]+$/)[0]; + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[basename(e.filename)]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)\\]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args || [], index, env.filename, important); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules, env.strictImports); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, index); + } + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Media)(rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value, features) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value); +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, index) { + var that = this; + + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root) { + if (e) { e.index = index } + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var el = new(tree.Element)('&', null, 0), + selectors = [new(tree.Selector)([el])]; + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var el = new(tree.Element)('&', null, 0); + var selectors = [new(tree.Selector)([el])]; + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs; + + for (var i = 0, val, name; i < this.params.length; i++) { + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors(paths, context, this.selectors); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join( env.compress ? ',' : ',\n'); + + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = (location.protocol === 'file:' || + location.protocol === 'chrome:' || + location.protocol === 'chrome-extension:' || + location.protocol === 'resource:'); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^(https?|file):/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + var filename = href.match(/([^\/]+)$/)[1]; + + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: filename + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + css.media = sheet.media || 'screen'; + css.id = id; + document.getElementsByTagName('head')[0].appendChild(css); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? false : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.0.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.0.min.js new file mode 100644 index 000000000..309bf550d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.0.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.0 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,b){var c=y(a,b),d=z(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&z(a.call,c).line+1,this.callExtract=g[z(a.call,c).line],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var b,f,g,h,i,j,k,l,m,n=this,o=function(){},p=this.imports={paths:a&&a.paths||[],queue:[],files:{},contents:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d,f){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,e.contents[b]=f,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&o()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,m={imports:p,parse:function(h,i){var n,p,q,r,s,u,v=[],w,x=null;f=g=l=j=0,b=h.replace(/\r\n/g,"\n"),k=function(c){var d=0,e=/[^"'`\{\}\/\(\)\\]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=c[0],k;for(var l=0,m,n;l0&&(x=new A({index:l,type:"Parse",message:"missing closing `}`",filename:a.filename},a)),c.map(function(a){return a.join("")})}([[]]);if(x)return i(x);try{n=new e.Ruleset([],t(this.parsers.primary)),n.root=!0}catch(y){return i(new A(y,a))}n.toCSS=function(b){var f,g,h;return function(f,g){var h=[],i;f=f||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),h=[new e.Ruleset(null,g)]);try{var j=b.call(this,{frames:h}).toCSS([],{compress:f.compress||!1})}catch(k){throw new A(k,a)}if(i=m.imports.error)throw i instanceof A?i:new A(i,a);return f.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):f.compress?j.replace(/(\s)+/g,"$1"):j}}(n.eval);if(f=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:f,filename:a.filename,line:s,column:B,extract:[u[s-2],u[s-1],u[s]]}}this.imports.queue.length>0?o=function(){i(x,n)}:i(x,n)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var b,c,d=f;if(!(b=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;b=b[1].toLowerCase();if(b==="url")return null;f+=b.length;if(b==="alpha")return t(this.alpha);t("("),c=t(this.entities.arguments);if(!t(")"))return;if(b)return new e.Call(b,c,d,a.filename)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;return a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"",u(")"),new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var c,d=f;if(b.charAt(f)==="@"&&(c=t(/^@@?[\w-]+/)))return new e.Variable(c,d,a.filename)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!w(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var c=[],d,g,h,i=f,j=b.charAt(f),k=!1;if(j!=="."&&j!=="#")return;while(d=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))c.push(new e.Element(g,d,f)),g=t(">");t("(")&&(h=t(this.entities.arguments))&&t(")"),t(this.important)&&(k=!0);if(c.length>0&&(t(";")||w("}")))return new e.mixin.Call(c,h||[],i,a.filename,k)},definition:function(){var a,c=[],d,g,h,i,j,k=!1;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||w(/^[^{]*(;|})/))return;q();if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];do{if(b.charAt(f)==="."&&t(/^\.{3}/)){k=!0;break}if(!(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)))break;if(h instanceof e.Variable)if(t(":"))i=u(this.expression,"expected expression"),c.push({name:h.name,value:i});else{if(t(/^\.{3}/)){c.push({name:h.name,variadic:!0}),k=!0;break}c.push({name:h.name})}else c.push({value:h})}while(t(","));u(")"),t(/^when/)&&(j=u(this.conditions,"expected condition")),g=t(this.block);if(g)return new e.mixin.Definition(a,c,g,j,k);r()}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||w("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable))return u(")"),new e.Alpha(a)},element:function(){var a,b,c,d;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/),a||t("(")&&(d=t(this.entities.variable))&&t(")")&&(a=new e.Paren(d));if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;if(t("("))return a=t(this.entity),u(")"),new e.Selector([new e.Element("",a,f)]);while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var b=[],c,d,g;q();while(c=t(this.selector)){b.push(c),t(this.comment);if(!t(","))break;t(this.comment)}if(b.length>0&&(d=t(this.block)))return new e.Ruleset(b,d,a.strictImports);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a,b,c=f;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))){b=t(this.mediaFeatures);if(t(";"))return new e.Import(a,p,b,c)}},mediaFeature:function(){var a,b,c=[];do if(a=t(this.entities.keyword))c.push(a);else if(t("(")){b=t(this.property),a=t(this.entity);if(!t(")"))return null;if(b&&a)c.push(new e.Paren(new e.Rule(b,a,null,f,!0)));else if(a)c.push(new e.Paren(a));else return null}while(a);if(c.length>0)return new e.Expression(c)},mediaFeatures:function(){var a,b=[];do if(a=t(this.mediaFeature)){b.push(a);if(!t(","))break}else if(a=t(this.entities.variable)){b.push(a);if(!t(","))break}while(a);return b.length>0?b:null},media:function(){var a,b;if(t(/^@media/)){a=t(this.mediaFeatures);if(b=t(this.block))return new e.Media(b,a)}},directive:function(){var a,c,d,g,h,i;if(b.charAt(f)!=="@")return;if(c=t(this["import"])||t(this.media))return c;if(a=t(/^@page|@keyframes/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!w(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},conditions:function(){var a,b,c=f,d;if(a=t(this.condition)){while(t(",")&&(b=t(this.condition)))d=new e.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,g=f,h=!1;t(/^not/)&&(h=!0),u("(");if(a=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))return(d=t(/^(?:>=|=<|[<=>])/))?(b=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))?c=new e.Condition(d,a,b,g,h):v("expected expression"):c=new e.Condition("=",a,new e.Keyword("true"),g,h),u(")"),t(/^and/)?new e.Condition("and",c,t(this.condition)):c},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e1){var d=new a.Element("&",null,0),e=[new a.Selector([d])];c=new a.Ruleset(e,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(a.length===0)return[];if(a.length===1)return a[0];var b=[],c=this.permute(a.slice(1));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;gthis.params.length)return!1;if(this.required>0&&c>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c,d,e){b&&p(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = path in that.files; + + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + } + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { + e = new(tree.Paren)(v); + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ + loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) + * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); + } else if (typeof(n) === 'number') { + return n.toFixed(fraction); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs, arg; + + for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] + + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; + } + + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (arg && arg.value) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push((args[i] && args[i].value) || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules = []; + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + rules = []; + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + this.value = val; + this.paths = paths; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx); + + // Add the base path if the URL is relative and we are in the browser + if (typeof window !== 'undefined' && typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value) && this.paths.length > 0) { + val.value = this.paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + + return new(tree.URL)(val, this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +// +// Watch mode +// +less.watch = function () { return this.watchMode = true }; +less.unwatch = function () { return this.watchMode = false }; + +if (less.env === 'development') { + less.optimization = 0; + + if (/!watch/.test(location.hash)) { + less.watch(); + } + var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); + if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; + } + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); +} else { + less.optimization = 3; +} + +var cache; + +try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; +} catch (_) { + cache = null; +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)({ + filename: document.location.href.replace(/#.*$/, ''), + dumpLineNumbers: less.dumpLineNumbers + }).parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var contents = sheet.contents || {}; // Passing a ref to top importing parser content cache trough 'sheet' arg. + var url = window.location.href.replace(/[#?].*$/, ''); + var href = sheet.href.replace(/\?.*$/, ''); + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + + // Stylesheets in IE don't always return the full path + if (! /^[a-z-]+:/.test(href)) { + if (href.charAt(0) == "/") { + href = window.location.protocol + "//" + window.location.host + href; + } else { + href = url.slice(0, url.lastIndexOf('/') + 1) + href; + } + } + xhr(sheet.href, sheet.type, function (data, lastModified) { + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }); + } else { + // Use remote copy (re-parse) + try { + contents[href] = data; // Updating top importing parser content cache + new(less.Parser)({ + optimization: less.optimization, + paths: [href.replace(/[\w\.-]+$/, '')], + mime: sheet.type, + filename: href, + 'contents': contents, // Passing top importing parser content cache ref down. + dumpLineNumbers: less.dumpLineNumbers + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\?.*$/, '' ) // Remove query + .replace(/\.[^\.\/]+$/, '' ) // Remove file extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + if( sheet.media ){ css.media = sheet.media; } + css.id = id; + var nextEl = sheet && sheet.nextSibling || null; + document.getElementsByTagName('head')[0].insertBefore(css, nextEl); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + var filenameNoPath = filename.match(/([^\/]+)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define("less", [], function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.1.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.1.min.js new file mode 100644 index 000000000..4043d44f3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.1.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.1 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(e,t){function n(t){return e.less[t.split("/")[1]]}function h(){var e=document.getElementsByTagName("style");for(var t=0;t0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&u){w("saving "+i+" to cache.");try{u.setItem(i,e),u.setItem(i+":timestamp",n)}catch(a){w("failed to save")}}}function g(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var o=y(),u=s?r.fileAsync:r.async;typeof o.overrideMimeType=="function"&&o.overrideMimeType("text/css"),o.open("GET",e,u),o.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),o.send(null),s&&!r.fileAsync?o.status===0||o.status>=200&&o.status<300?n(o.responseText):i(o.status,e):u?o.onreadystatechange=function(){o.readyState==4&&a(o,n,i)}:a(o,n,i)}function y(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return w("browser doesn't support AJAX."),null}}function b(e){return e&&e.parentNode.removeChild(e)}function w(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function E(e,t){var n="less-error-message:"+v(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,m([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={});var v=function(){},m=this.imports={paths:t&&t.paths||[],queue:[],files:{},contents:t.contents,mime:t&&t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r){i.queue.splice(i.queue.indexOf(e),1);var s=e in i.files;i.files[e]=r,t&&!i.error&&(i.error=t),n(t,r,s),i.queue.length===0&&v(t)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0&&(x=new O({index:c,type:"Parse",message:"missing closing `}`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("./cssmin").compressor.cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),m.paths)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<45||t===47)return;if(e=E(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a,f=o,l=s.charAt(o),c,h,p=!1;if(l!=="."&&l!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){while(a=E(this.expression)){h=a,c=null;if(a.value.length==1){var d=a.value[0];if(d instanceof i.Variable&&E(":")){if(!(h=E(this.expression)))throw new Error("Expected value");c=d.name}}u.push({name:c,value:h});if(!E(","))break}if(!E(")"))throw new Error("Expected )")}E(this.important)&&(p=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,u,f,t.filename,p);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*(;|})/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0;break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(","));E(")")||(l=o,y()),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^)@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),x(")"),new i.Selector([new i.Element("",e,o)]);while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===",")break}if(n.length>0)return new i.Selector(n)},tag:function(){return E(/^[A-Za-z][A-Za-z-]*[0-9]?/)||E("*")},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,t,n=o;g();var r=E(/^@import(?:-(once))?\s+/);if(r&&(e=E(this.entities.quoted)||E(this.entities.url))){t=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,t,r[1]==="once",n)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,t,n,r,u,a,f,l,c;if(s.charAt(o)!=="@")return;if(t=E(this["import"])||E(this.media))return t;g(),e=E(/^@[a-z-]+/),f=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(f="@"+e.slice(e.indexOf("-",2)+1));switch(f){case"@font-face":l=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":l=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":l=!0,c=!0}c&&(e+=" "+(E(/^[^{]+/)||"").trim());if(l){if(n=E(this.block))return new i.Directive(e,n)}else if((t=E(this.entity))&&E(";"))return new i.Directive(e,t);y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/\*/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),d({href:e,title:e,type:r.mime,contents:r.contents},function(i){i&&typeof r.errback=="function"?r.errback.call(null,e,t,n,r):n.apply(null,arguments)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function r(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,r,i,s){var o=[t,r,i].map(function(e){return n(e)}),s=n(s);return new e.Color(o,s)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,r,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=n(e)%360/360,t=n(t),r=n(r),i=n(i);var s=r<=.5?r*(t+1):r+t-r*t,o=r*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var i=e.toHSL();return i.s+=n.value/100,i.s=r(i.s),t(i)},desaturate:function(e,n){var i=e.toHSL();return i.s-=n.value/100,i.s=r(i.s),t(i)},lighten:function(e,n){var i=e.toHSL();return i.l+=n.value/100,i.l=r(i.l),t(i)},darken:function(e,n){var i=e.toHSL();return i.l-=n.value/100,i.l=r(i.l),t(i)},fadein:function(e,n){var i=e.toHSL();return i.a+=n.value/100,i.a=r(i.a),t(i)},fadeout:function(e,n){var i=e.toHSL();return i.a-=n.value/100,i.a=r(i.a),t(i)},fade:function(e,n){var i=e.toHSL();return i.a=n.value/100,i.a=r(i.a),t(i)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t, +n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s){var o=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),t instanceof e.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css(\?.*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&o.once&&(o.skip=r),o.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?"@import "+this._path.toCSS()+t+";\n":""},eval:function(t){var n,r=this.features&&this.features.eval(t);if(this.skip)return[];if(this.css)return this;n=new e.Ruleset([],this.root.rules.slice(0));for(var i=0;i1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){n=this.arguments&&this.arguments.map(function(t){return{name:t.name,value:t.value.eval(e)}});for(var o=0;othis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(t,e)].concat(t.frames)}))return!1;r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements.length,n=e.elements.length,r=Math.min(t,n);if(t0&&(r.value=this.paths[0]+(r.value.charAt(0)==="/"?r.value.slice(1):r.value)),new t.URL(r,this.paths)}}}(n("../tree")),function(e){e.Value=function(e){this.value=e,this.is="value"},e.Value.prototype={eval:function(t){return this.value.length===1?this.value[0].eval(t):new e.Value(this.value.map(function(e){return e.eval(t)}))},toCSS:function(e){return this.value.map(function(t){return t.toCSS(e)}).join(e.compress?",":", ")}}}(n("../tree")),function(e){e.Variable=function(e,t,n){this.name=e,this.index=t,this.file=n},e.Variable.prototype={eval:function(t){var n,r,i=this.name;i.indexOf("@@")==0&&(i="@"+(new e.Variable(i.slice(1))).eval(t).value);if(n=e.find(t.frames,function(e){if(r=e.variable(i))return r.value.eval(t)}))return n;throw{type:"Name",message:"variable "+i+" is undefined",filename:this.file,index:this.index}}}}(n("../tree")),function(e){e.debugInfo=function(t,n){var r="";if(t.dumpLineNumbers&&!t.compress)switch(t.dumpLineNumbers){case"comments":r=e.debugInfo.asComment(n);break;case"mediaquery":r=e.debugInfo.asMediaQuery(n);break;case"all":r=e.debugInfo.asComment(n)+e.debugInfo.asMediaQuery(n)}return r},e.debugInfo.asComment=function(e){return"/* line "+e.debugInfo.lineNumber+", "+e.debugInfo.fileName+" */\n"},e.debugInfo.asMediaQuery=function(e){return'@media -sass-debug-info{filename{font-family:"'+e.debugInfo.fileName+'";}line{font-family:"'+e.debugInfo.lineNumber+'";}}\n'},e.find=function(e,t){for(var n=0,r;n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var s=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||s?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(s?1e3:1500),r.watch=function(){return this.watchMode=!0},r.unwatch=function(){return this.watchMode=!1};if(r.env==="development"){r.optimization=0,/!watch/.test(location.hash)&&r.watch();var o=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);o&&(r.dumpLineNumbers=o[1]),r.watchTimer=setInterval(function(){r.watchMode&&p(function(e,t,n,r,i){t&&m(t.toCSS(),r,i.lastModified)})},r.poll)}else r.optimization=3;var u;try{u=typeof e.localStorage=="undefined"?null:e.localStorage}catch(a){u=null}var f=document.getElementsByTagName("link"),l=/^text\/(x-)?less$/;r.sheets=[];for(var c=0;c>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree, charset; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + // env.contents and files must be passed arround with top env + if (!env.contents) { env.contents = {}; } + env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided + if (!env.files) { env.files = {}; } + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, fullPath) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = fullPath in that.files; + + that.files[fullPath] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error, env); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + e = error || e; + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.rootpath); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + expressions = []; + while (arg = $(this.expression)) { + nameLoop = null; + value = arg; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } + } + } + + expressions.push(value); + + argsComma.push({ name: nameLoop, value: value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name: name, value: value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + expect(')'); + } + + args = isSemiColonSeperated ? argsSemiColon : argsComma; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + params.push({ variadic: true }); + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',') || $(';')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.entities.variableCurly) || + $(this.entities.variable) || + $(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ + href: path, + title: path, + type: env.mime, + contents: env.contents, + files: env.files, + rootpath: env.rootpath, + entryPath: env.entryPath, + relativeUrls: env.relativeUrls }, + function (e, root, data, sheet, _, path) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.call(null, e, root, path); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) * + color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, n); + }, + ceil: function (n) { + return this._math(Math.ceil, n); + }, + floor: function (n) { + return this._math(Math.floor, n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit == '%') { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + if (other.unit && this.unit !== other.unit) { + return -1; + } + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index, rootpath) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + this.rootpath = rootpath; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /(\.[a-z]*$)|([\?;].*)$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css([\?;].*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + // Add the base path if the import is relative + if (typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) { + this._path.value = this.rootpath + this._path.value; + } + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), varargs, arg, params = this.params.slice(0), i, j, val, name, isNamedFound, argIndex; + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, {frames: mixinFrames}, args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(mixinFrames) + }); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, {frames: this.frames.concat(env.frames)}, args, [])].concat(env.frames) + })) { return false } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { name: "OperationError", + message: "Operation on an invalid type" }; + } + + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Rule.prototype.makeImportant = function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(paths, env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen) + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, rootpath) { + this.value = val; + this.rootpath = rootpath; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + if (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) { + rootpath = this.rootpath; + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, this.rootpath); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)().parse(str, function (e, root) { + createCSS(root.toCSS(), less.sheets[less.sheets.length - 1]); + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)({ + filename: document.location.href.replace(/#.*$/, ''), + dumpLineNumbers: less.dumpLineNumbers + }).parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/\/(?:[^\/\?#]+\/)|([\/\\]))?((?:[^\/\\\?#]+[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = baseUrlParts[1]; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace("\\", "/").split("/"); + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var contents = sheet.contents || {}; + var files = sheet.files || {}; + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var rootpath; + + if (less.relativeUrls) { + if (less.rootpath) { + if (sheet.entryPath) { + rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, sheet.entryPath)).path; + } else { + rootpath = less.rootpath; + } + } else { + rootpath = hrefParts.path; + } + } else { + if (less.rootpath) { + rootpath = less.rootpath; + } else { + if (sheet.entryPath) { + rootpath = sheet.entryPath; + } else { + rootpath = hrefParts.path; + } + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + contents[href] = data; // Updating top importing parser content cache + new(less.Parser)({ + optimization: less.optimization, + paths: [hrefParts.path], + entryPath: sheet.entryPath || hrefParts.path, + mime: sheet.type, + filename: href, + rootpath: rootpath, + relativeUrls: sheet.relativeUrls, + contents: contents, // Passing top importing parser content cache ref down. + files: files, + dumpLineNumbers: less.dumpLineNumbers + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + if( sheet.media ){ css.media = sheet.media; } + css.id = id; + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define("less", [], function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.2.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.2.min.js new file mode 100644 index 000000000..5985526ee --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.2.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.2 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,r,i){t&&S(t.toCSS(),r,i.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=t.contents||{},u=t.files||{},a=b(t.href,e.location.href),f=a.url,c=l&&l.getItem(f),h=l&&l.getItem(f+":timestamp"),p={css:c,timestamp:h},d;r.relativeUrls?r.rootpath?t.entryPath?d=b(r.rootpath+y(a.path,t.entryPath)).path:d=r.rootpath:d=a.path:r.rootpath?d=r.rootpath:t.entryPath?d=t.entryPath:d=a.path,x(f,t.type,function(e,l){v+=e.replace(/@import .+?;/ig,"");if(!i&&p&&l&&(new Date(l)).valueOf()===(new Date(p.timestamp)).valueOf())S(p.css,t),n(null,null,e,t,{local:!0,remaining:s},f);else try{o[f]=e,(new r.Parser({optimization:r.optimization,paths:[a.path],entryPath:t.entryPath||a.path,mime:t.type,filename:f,rootpath:d,relativeUrls:t.relativeUrls,contents:o,files:u,dumpLineNumbers:r.dumpLineNumbers})).parse(e,function(r,i){if(r)return k(r,f);try{n(r,i,e,t,{local:!1,lastModified:l,remaining:s},f),N(document.getElementById("less-error-message:"+E(f)))}catch(r){k(r,f)}})}catch(c){k(c,f)}},function(e,t){throw new Error("Couldn't load "+t+" ("+e+")")})}function E(e){return e.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r,i=t.href||"",s="less:"+(t.title||E(i));if((r=document.getElementById(s))===null){r=document.createElement("style"),r.type="text/css",t.media&&(r.media=t.media),r.id=s;var o=t&&t.nextSibling||null;(o||document.getElementsByTagName("head")[0]).parentNode.insertBefore(r,o)}if(r.styleSheet)try{r.styleSheet.cssText=e}catch(u){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(e){r.childNodes.length>0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&l){C("saving "+i+" to cache.");try{l.setItem(i,e),l.setItem(i+":timestamp",n)}catch(u){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,t){var n="less-error-message:"+E(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+(\?.*)?)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={}),t.rootpath=t.rootpath||"",t.files||(t.files={});var v=function(){},m=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r,s){i.queue.splice(i.queue.indexOf(e),1);var o=s in i.files;i.files[s]=r,t&&!i.error&&(i.error=t),n(t,r,o),i.queue.length===0&&v(i.error)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x,t);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e=x||e,e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/)||E(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)||E(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.rootpath)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=E(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},unicodeDescriptor:function(){var e;if(e=E(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a=[],f,l,c,h,p,d,v,m=o,b=s.charAt(o),w,S,C=!1;if(b!=="."&&b!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){p=[];while(c=E(this.expression)){h=null,S=c;if(c.value.length==1){var k=c.value[0];k instanceof i.Variable&&E(":")&&(p.length>0&&(d&&T("Cannot mix ; and , as delimiter types"),v=!0),S=x(this.expression),h=w=k.name)}p.push(S),a.push({name:h,value:S});if(E(","))continue;if(E(";")||d)v&&T("Cannot mix ; and , as delimiter types"),d=!0,p.length>1&&(S=new i.Value(p)),u.push({name:w,value:S}),w=null,p=[],v=!1}x(")")}f=d?u:a,E(this.important)&&(C=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,f,m,t.filename,C);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*\}/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{E(this.comment);if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0,t.push({variadic:!0});break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(",")||E(";"));E(")")||(l=o,y()),E(this.comment),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^()@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable)||E(this.selector))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),x(")"),new i.Selector([new i.Element("",e,o)]);while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n)},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,n,r=o;g();var s=E(/^@import(?:-(once))?\s+/);if(s&&(e=E(this.entities.quoted)||E(this.entities.url))){n=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,n,s[1]==="once",r,t.rootpath)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=E(this["import"])||E(this.media))return n;g(),e=E(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(E(/^[^{]+/)||"").trim());if(c){if(r=E(this.block))return new i.Directive(e,r)}else if((n=p?E(this.expression):E(this.entity))&&E(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=A(o,s,t)),d}y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/[*\/]/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),w({href:e,title:e,type:r.mime,contents:r.contents,files:r.files,rootpath:r.rootpath,entryPath:r.entryPath,relativeUrls:r.relativeUrls},function(e,i,s,o,u,a){e&&typeof r.errback=="function"?r.errback.call(null,a,t,n,r):n.call(null,e,i,a)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t,n){return t instanceof e.Dimension&&t.unit=="%"?parseFloat(t.value*n/100):r(t)}function r(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function i(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,i,s,o){var u=[t,i,s].map(function(e){return n(e,256)});return o=r(o),new e.Color(u,o)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=r(e)%360/360,t=r(t),n=r(n),i=r(i);var s=n<=.5?n*(t+1):n+t-n*t,o=n*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,i){e=r(e)%360/360*360,t=r(t),n=r(n),i=r(i);var s,o;s=Math.floor(e/60%6),o=e/60-s;var u=[n,n*(1-t),n*(1-o*t),n*(1-(1-o)*t)],a=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(u[a[s][0]]*255,u[a[s][1]]*255,u[a[s][2]]*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var r=e.toHSL();return r.s+=n.value/100,r.s=i(r.s),t(r)},desaturate:function(e,n){var r=e.toHSL();return r.s-=n.value/100,r.s=i(r.s),t(r)},lighten:function(e,n){var r=e.toHSL();return r.l+=n.value/100,r.l=i(r.l),t(r)},darken:function(e,n){var r=e.toHSL();return r.l-=n.value/100,r.l=i(r.l),t(r)},fadein:function(e,n){var r=e.toHSL();return r.a+=n.value/100,r.a=i(r.a),t(r)},fadeout:function(e,n){var r=e.toHSL();return r.a-=n.value/100,r.a=i(r.a),t(r)},fade:function(e,n){var r=e.toHSL();return r.a=n.value/100,r.a=i(r.a),t(r)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s,o){var u=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),this.rootpath=o,t instanceof e.Quoted?this.path=/(\.[a-z]*$)|([\?;].*)$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css([\?;].*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&u.once&&(u.skip=r),u.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?(typeof this._path.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(this._path.value)&&(this._path.value=this.rootpath+this._path.value),"@import "+this._path.toCSS()+t+";\n"):""},eval:function(t){var n,r=this.features&&this.features.eval(t);return this.skip?[]:this.css?this:(n=new e.Ruleset([],this.root.rules.slice(0)),n.evalImports(t),this.features?new e.Media(n.rules,this.features.value):n.rules)}}}(n("../tree")),function(e){e.JavaScript=function(e,t,n){this.escaped=n,this.expression=e,this.index=t},e.JavaScript.prototype={eval:function(t){var n,r=this,i={},s=this.expression.replace(/@\{([\w-]+)\}/g,function(n,i){return e.jsify((new e.Variable("@"+i,r.index)).eval(t))});try{s=new Function("return ("+s+")")}catch(o){throw{message:"JavaScript evaluation error: `"+s+"`",index:this.index}}for(var u in t.frames[0].variables())i[u.slice(1)]={value:t.frames[0].variables()[u].value,toJS:function(){return this.value.eval(t).toCSS()}};try{n=s.call(i)}catch(o){throw{message:"JavaScript evaluation error: '"+o.name+": "+o.message+"'",index:this.index}}return typeof n=="string"?new e.Quoted('"'+n+'"',n,this.escaped,this.index):Array.isArray(n)?new e.Anonymous(n.join(", ")):new e.Anonymous(n)}}}(n("../tree")),function(e){e.Keyword=function(e){this.value=e},e.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(t){return t instanceof e.Keyword?t.value===this.value?0:1:-1}},e.True=new e.Keyword("true"),e.False=new e.Keyword("false")}(n("../tree")),function(e){e.Media=function(t,n){var r=this.emptySelectors();this.features=new e.Value(n),this.ruleset=new e.Ruleset(r,t),this.ruleset.allowImports=!0},e.Media.prototype={toCSS:function(e,t){var n=this.features.toCSS(t);return this.ruleset.root=e.length===0||e[0].multiMedia,"@media "+n+(t.compress?"{":" {\n ")+this.ruleset.toCSS(e,t).trim().replace(/\n/g,"\n ")+(t.compress?"}":"\n}\n")},eval:function(t){t.mediaBlocks||(t.mediaBlocks=[],t.mediaPath=[]);var n=new e.Media([],[]);return this.debugInfo&&(this.ruleset.debugInfo=this.debugInfo,n.debugInfo=this.debugInfo),n.features=this.features.eval(t),t.mediaPath.push(n),t.mediaBlocks.push(n),t.frames.unshift(this.ruleset),n.ruleset=this.ruleset.eval(t),t.frames.shift(),t.mediaPath.pop(),t.mediaPath.length===0?n.evalTop(t):n.evalNested(t)},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)},emptySelectors:function(){var t=new e.Element("","&",0);return[new e.Selector([t])]},evalTop:function(t){var n=this;if(t.mediaBlocks.length>1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree, charset; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + // env.contents and files must be passed arround with top env + if (!env.contents) { env.contents = {}; } + env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided + if (!env.files) { env.files = {}; } + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, fullPath) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = fullPath in that.files; + + that.files[fullPath] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error, env); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + e = error || e; + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.rootpath); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + expressions = []; + while (arg = $(this.expression)) { + nameLoop = null; + value = arg; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } + } + } + + expressions.push(value); + + argsComma.push({ name: nameLoop, value: value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name: name, value: value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + expect(')'); + } + + args = isSemiColonSeperated ? argsSemiColon : argsComma; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + params.push({ variadic: true }); + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',') || $(';')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.entities.variableCurly) || + $(this.entities.variable) || + $(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + if (!$(')')) { return null; } + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ + href: path, + title: path, + type: env.mime, + contents: env.contents, + files: env.files, + rootpath: env.rootpath, + entryPath: env.entryPath, + relativeUrls: env.relativeUrls }, + function (e, root, data, sheet, _, path) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.call(null, e, root, path); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) * + color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, n); + }, + ceil: function (n) { + return this._math(Math.ceil, n); + }, + floor: function (n) { + return this._math(Math.floor, n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit == '%') { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }), + result; + + if (this.name in tree.functions) { // 1. + try { + result = tree.functions[this.name].apply(tree.functions, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + if (other.unit && this.unit !== other.unit) { + return -1; + } + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index, rootpath) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + this.rootpath = rootpath; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /(\.[a-z]*$)|([\?;].*)$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css([\?;].*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + // Add the base path if the import is relative + if (typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) { + this._path.value = this.rootpath + this._path.value; + } + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), varargs, arg, params = this.params.slice(0), i, j, val, name, isNamedFound, argIndex; + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, {frames: mixinFrames}, args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(mixinFrames) + }); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, {frames: this.frames.concat(env.frames)}, args, [])].concat(env.frames) + })) { return false } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { name: "OperationError", + message: "Operation on an invalid type" }; + } + + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Rule.prototype.makeImportant = function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(paths, env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen) + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, rootpath) { + this.value = val; + this.rootpath = rootpath; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + if (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) { + rootpath = this.rootpath; + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, this.rootpath); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (root) { + createCSS(root.toCSS(), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)().parse(str, function (e, root) { + createCSS(root.toCSS(), less.sheets[less.sheets.length - 1]); + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + new(less.Parser)({ + filename: document.location.href.replace(/#.*$/, ''), + dumpLineNumbers: less.dumpLineNumbers + }).parse(styles[i].innerHTML || '', function (e, tree) { + var css = tree.toCSS(); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/\/(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = baseUrlParts[1]; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace("\\", "/").split("/"); + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var contents = sheet.contents || {}; + var files = sheet.files || {}; + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var rootpath; + + if (less.relativeUrls) { + if (less.rootpath) { + if (sheet.entryPath) { + rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, sheet.entryPath)).path; + } else { + rootpath = less.rootpath; + } + } else { + rootpath = hrefParts.path; + } + } else { + if (less.rootpath) { + rootpath = less.rootpath; + } else { + if (sheet.entryPath) { + rootpath = sheet.entryPath; + } else { + rootpath = hrefParts.path; + } + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + contents[href] = data; // Updating top importing parser content cache + new(less.Parser)({ + optimization: less.optimization, + paths: [hrefParts.path], + entryPath: sheet.entryPath || hrefParts.path, + mime: sheet.type, + filename: href, + rootpath: rootpath, + relativeUrls: sheet.relativeUrls, + contents: contents, // Passing top importing parser content cache ref down. + files: files, + dumpLineNumbers: less.dumpLineNumbers + }).parse(data, function (e, root) { + if (e) { return error(e, href) } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } catch (e) { + error(e, href); + } + }); + } catch (e) { + error(e, href); + } + } + }, function (status, url) { + throw new(Error)("Couldn't load " + url + " (" + status + ")"); + }); +} + +function extractId(href) { + return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + var css; + + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If the stylesheet doesn't exist, create a new node + if ((css = document.getElementById(id)) === null) { + css = document.createElement('style'); + css.type = 'text/css'; + if( sheet.media ){ css.media = sheet.media; } + css.id = id; + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + (function (node) { + if (css.childNodes.length > 0) { + if (css.firstChild.nodeValue !== node.nodeValue) { + css.replaceChild(node, css.firstChild); + } + } else { + css.appendChild(node); + } + })(document.createTextNode(styles)); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, href) { + var id = 'less-error-message:' + extractId(href); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || href; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } else if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define("less", [], function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.3.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.3.min.js new file mode 100644 index 000000000..9b0fa6bae --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.3.3.min.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.3 +// http://lesscss.org +// +// Copyright (c) 2009-2013, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,r,i){t&&S(t.toCSS(),r,i.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=t.contents||{},u=t.files||{},a=b(t.href,e.location.href),f=a.url,c=l&&l.getItem(f),h=l&&l.getItem(f+":timestamp"),p={css:c,timestamp:h},d;r.relativeUrls?r.rootpath?t.entryPath?d=b(r.rootpath+y(a.path,t.entryPath)).path:d=r.rootpath:d=a.path:r.rootpath?d=r.rootpath:t.entryPath?d=t.entryPath:d=a.path,x(f,t.type,function(e,l){v+=e.replace(/@import .+?;/ig,"");if(!i&&p&&l&&(new Date(l)).valueOf()===(new Date(p.timestamp)).valueOf())S(p.css,t),n(null,null,e,t,{local:!0,remaining:s},f);else try{o[f]=e,(new r.Parser({optimization:r.optimization,paths:[a.path],entryPath:t.entryPath||a.path,mime:t.type,filename:f,rootpath:d,relativeUrls:t.relativeUrls,contents:o,files:u,dumpLineNumbers:r.dumpLineNumbers})).parse(e,function(r,i){if(r)return k(r,f);try{n(r,i,e,t,{local:!1,lastModified:l,remaining:s},f),N(document.getElementById("less-error-message:"+E(f)))}catch(r){k(r,f)}})}catch(c){k(c,f)}},function(e,t){throw new Error("Couldn't load "+t+" ("+e+")")})}function E(e){return e.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r,i=t.href||"",s="less:"+(t.title||E(i));if((r=document.getElementById(s))===null){r=document.createElement("style"),r.type="text/css",t.media&&(r.media=t.media),r.id=s;var o=t&&t.nextSibling||null;(o||document.getElementsByTagName("head")[0]).parentNode.insertBefore(r,o)}if(r.styleSheet)try{r.styleSheet.cssText=e}catch(u){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(e){r.childNodes.length>0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&l){C("saving "+i+" to cache.");try{l.setItem(i,e),l.setItem(i+":timestamp",n)}catch(u){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,t){var n="less-error-message:"+E(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+(\?.*)?)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={}),t.rootpath=t.rootpath||"",t.files||(t.files={});var v=function(){},m=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r,s){i.queue.splice(i.queue.indexOf(e),1);var o=s in i.files;i.files[s]=r,t&&!i.error&&(i.error=t),n(t,r,o),i.queue.length===0&&v(i.error)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x,t);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e=x||e,e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/)||E(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)||E(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.rootpath)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=E(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},unicodeDescriptor:function(){var e;if(e=E(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a=[],f,l,c,h,p,d,v,m=o,b=s.charAt(o),w,S,C=!1;if(b!=="."&&b!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){p=[];while(c=E(this.expression)){h=null,S=c;if(c.value.length==1){var k=c.value[0];k instanceof i.Variable&&E(":")&&(p.length>0&&(d&&T("Cannot mix ; and , as delimiter types"),v=!0),S=x(this.expression),h=w=k.name)}p.push(S),a.push({name:h,value:S});if(E(","))continue;if(E(";")||d)v&&T("Cannot mix ; and , as delimiter types"),d=!0,p.length>1&&(S=new i.Value(p)),u.push({name:w,value:S}),w=null,p=[],v=!1}x(")")}f=d?u:a,E(this.important)&&(C=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,f,m,t.filename,C);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*\}/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{E(this.comment);if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0,t.push({variadic:!0});break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(",")||E(";"));E(")")||(l=o,y()),E(this.comment),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^()@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable)||E(this.selector))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),E(")")?new i.Selector([new i.Element("",e,o)]):null;while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n)},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,n,r=o;g();var s=E(/^@import(?:-(once))?\s+/);if(s&&(e=E(this.entities.quoted)||E(this.entities.url))){n=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,n,s[1]==="once",r,t.rootpath)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=E(this["import"])||E(this.media))return n;g(),e=E(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(E(/^[^{]+/)||"").trim());if(c){if(r=E(this.block))return new i.Directive(e,r)}else if((n=p?E(this.expression):E(this.entity))&&E(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=A(o,s,t)),d}y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/[*\/]/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),w({href:e,title:e,type:r.mime,contents:r.contents,files:r.files,rootpath:r.rootpath,entryPath:r.entryPath,relativeUrls:r.relativeUrls},function(e,i,s,o,u,a){e&&typeof r.errback=="function"?r.errback.call(null,a,t,n,r):n.call(null,e,i,a)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t,n){return t instanceof e.Dimension&&t.unit=="%"?parseFloat(t.value*n/100):r(t)}function r(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function i(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,i,s,o){var u=[t,i,s].map(function(e){return n(e,256)});return o=r(o),new e.Color(u,o)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=r(e)%360/360,t=r(t),n=r(n),i=r(i);var s=n<=.5?n*(t+1):n+t-n*t,o=n*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,i){e=r(e)%360/360*360,t=r(t),n=r(n),i=r(i);var s,o;s=Math.floor(e/60%6),o=e/60-s;var u=[n,n*(1-t),n*(1-o*t),n*(1-(1-o)*t)],a=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(u[a[s][0]]*255,u[a[s][1]]*255,u[a[s][2]]*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var r=e.toHSL();return r.s+=n.value/100,r.s=i(r.s),t(r)},desaturate:function(e,n){var r=e.toHSL();return r.s-=n.value/100,r.s=i(r.s),t(r)},lighten:function(e,n){var r=e.toHSL();return r.l+=n.value/100,r.l=i(r.l),t(r)},darken:function(e,n){var r=e.toHSL();return r.l-=n.value/100,r.l=i(r.l),t(r)},fadein:function(e,n){var r=e.toHSL();return r.a+=n.value/100,r.a=i(r.a),t(r)},fadeout:function(e,n){var r=e.toHSL();return r.a-=n.value/100,r.a=i(r.a),t(r)},fade:function(e,n){var r=e.toHSL();return r.a=n.value/100,r.a=i(r.a),t(r)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return e.rgb?(typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s,o){var u=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),this.rootpath=o,t instanceof e.Quoted?this.path=/(\.[a-z]*$)|([\?;].*)$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css([\?;].*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&u.once&&(u.skip=r),u.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?(typeof this._path.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(this._path.value)&&(this._path.value=this.rootpath+this._path.value),"@import "+this._path.toCSS()+t+";\n"):""},eval:function(t){var n,r=this.features&&this.features.eval(t);return this.skip?[]:this.css?this:(n=new e.Ruleset([],this.root.rules.slice(0)),n.evalImports(t),this.features?new e.Media(n.rules,this.features.value):n.rules)}}}(n("../tree")),function(e){e.JavaScript=function(e,t,n){this.escaped=n,this.expression=e,this.index=t},e.JavaScript.prototype={eval:function(t){var n,r=this,i={},s=this.expression.replace(/@\{([\w-]+)\}/g,function(n,i){return e.jsify((new e.Variable("@"+i,r.index)).eval(t))});try{s=new Function("return ("+s+")")}catch(o){throw{message:"JavaScript evaluation error: `"+s+"`",index:this.index}}for(var u in t.frames[0].variables())i[u.slice(1)]={value:t.frames[0].variables()[u].value,toJS:function(){return this.value.eval(t).toCSS()}};try{n=s.call(i)}catch(o){throw{message:"JavaScript evaluation error: '"+o.name+": "+o.message+"'",index:this.index}}return typeof n=="string"?new e.Quoted('"'+n+'"',n,this.escaped,this.index):Array.isArray(n)?new e.Anonymous(n.join(", ")):new e.Anonymous(n)}}}(n("../tree")),function(e){e.Keyword=function(e){this.value=e},e.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(t){return t instanceof e.Keyword?t.value===this.value?0:1:-1}},e.True=new e.Keyword("true"),e.False=new e.Keyword("false")}(n("../tree")),function(e){e.Media=function(t,n){var r=this.emptySelectors();this.features=new e.Value(n),this.ruleset=new e.Ruleset(r,t),this.ruleset.allowImports=!0},e.Media.prototype={toCSS:function(e,t){var n=this.features.toCSS(t);return this.ruleset.root=e.length===0||e[0].multiMedia,"@media "+n+(t.compress?"{":" {\n ")+this.ruleset.toCSS(e,t).trim().replace(/\n/g,"\n ")+(t.compress?"}":"\n}\n")},eval:function(t){t.mediaBlocks||(t.mediaBlocks=[],t.mediaPath=[]);var n=new e.Media([],[]);return this.debugInfo&&(this.ruleset.debugInfo=this.debugInfo,n.debugInfo=this.debugInfo),n.features=this.features.eval(t),t.mediaPath.push(n),t.mediaBlocks.push(n),t.frames.unshift(this.ruleset),n.ruleset=this.ruleset.eval(t),t.frames.shift(),t.mediaPath.pop(),t.mediaPath.length===0?n.evalTop(t):n.evalNested(t)},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)},emptySelectors:function(){var t=new e.Element("","&",0);return[new e.Selector([t])]},evalTop:function(t){var n=this;if(t.mediaBlocks.length>1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + options = options || {}; + var importError, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + var css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css, options.maxLineLen); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + callback(e); + } + else { + callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")) + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, delim, arg, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match, extend, extendList = []; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e) + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced, expression = []; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, currentFileInfo, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && currentFileInfo.currentDirectory) { + path = currentFileInfo.currentDirectory + path; + } + var sheetEnv = env.toSheet(path); + sheetEnv.processImports = false; + sheetEnv.currentFileInfo = currentFileInfo; + + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet(sheetEnv, + function (e, root, data, sheet, _, path) { + callback.call(null, e, root, path); + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + return values.value[index]; + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) mimetype += ';base64'; + } + else { + useBase64 = /;base64$/.test(mimetype) + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } else if (!this.env.silent) { + // if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn + console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + }, + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + type: "Color", + eval: function () { return this }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + + if (compress) { + color = color.split(''); + + // Convert color to short format + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) { + color = color[0] + color[2] + color[4]; + } else { + color = color.join(''); + } + } + + return '#' + color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + type: "Comment", + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function (env) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && !this.unit.isAngle()) { + return strValue; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + return strValue + this.unit.toCSS(env); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit, derivedConversions = {}; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + + toCSS: function (env) { + if (this.numerator.length >= 1) { + return this.numerator[0]; + } + if (this.denominator.length >= 1) { + return this.denominator[0]; + } + if ((!env || !env.strictUnits) && this.backupUnit) { + return this.backupUnit; + } + return ""; + }, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isAngle: function () { + return tree.UnitConversions.angle.hasOwnProperty(this.toCSS()); + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + toCSS: function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + }, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = []; + + for(i = 0; i < selectors.length; i++) { + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + var that = this; + + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined) { + this.css = !this.options.less; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + this.root = visitor.visit(this.root); + }, + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this.path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && !(path instanceof tree.URL)) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + toCSS: function () { return this.value; }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.ruleset = visitor.visit(this.ruleset); + }, + toCSS: function (env) { + var features = this.features.toCSS(env); + + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + toCSS: function () { return ""; }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval(new(tree.evalEnv)(env, + [this, frame].concat(mixinFrames))); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] + .concat(env.frames)))) { + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '-' + this.value.toCSS(env); + }, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + toCSS: function (env) { + var separator = this.isSpaced ? " " : ""; + return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS(); + } +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.variable) { return "" } + else { + try { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + } + }, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && env.strictMath === false) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + this.selectors = visitor.visit(this.selectors); + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + if (this.firstRoot && rule instanceof tree.Rule) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null}; + } + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + // Remove last semicolon + if (env.compress && rules.length) { + rule = rules[rules.length - 1]; + if (rule.charAt(rule.length - 1) === ';') { + rules[rules.length - 1] = rule.substring(0, rule.length - 1); + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = this.paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([], selector.extendList); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel, extendList; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extendList) { + this.elements = elements; + this.extendList = extendList || []; +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList) + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + })); + }, + toCSS: function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { this.name = name, this.index = index, this.currentFileInfo = currentFileInfo }; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function(a){if(a=='\\') a = '\/'; return '\\' + a}) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'strictImports', // option - + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'mime', // browser only - mime type for sheet import + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' = absolute path to the entry file + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = options.filename || "input"; + options.filename = null; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: options.rootpath || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + tree.parseEnv.prototype.toSheet = function (path) { + var env = new tree.parseEnv(this); + env.href = path; + //env.title = path; + env.type = this.mime; + return env; + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits' // whether units need to evaluate correctly + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + } +})(require('./tree'));(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + } + }; + +})(require('./tree'));(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode; + + if (!importNode.css) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && !evaldImportNode.css) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + this._importer.push(importNode.getPath(), importNode.currentFileInfo, function (e, root, imported) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (imported && !importNode.options.multiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + } else { + subFinish(); + } + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree'));(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.ruleset.root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree'));(function (tree) { + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex == 0 && hackstackElementIndex == 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator == '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + return false; + }, + extendSelector:function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)) + )); + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selector.elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree'));// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)(new less.tree.parseEnv(less)).parse(str, function (e, root) { + if (e) { + error(e, "session_cache"); + } else { + createCSS(root.toCSS(less), less.sheets[less.sheets.length - 1]); + } + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + var env = new less.tree.parseEnv(less); + env.filename = document.location.href.replace(/#.*$/, ''); + + new(less.Parser)(env).parse(styles[i].innerHTML || '', function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace("\\", "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var env; + var newFileInfo = { + relativeUrls: less.relativeUrls, + currentDirectory: hrefParts.path, + filename: href + }; + + if (sheet instanceof less.tree.parseEnv) { + env = new less.tree.parseEnv(sheet); + newFileInfo.entryPath = env.currentFileInfo.entryPath; + newFileInfo.rootpath = env.currentFileInfo.rootpath; + newFileInfo.rootFilename = env.currentFileInfo.rootFilename; + } else { + env = new less.tree.parseEnv(less); + env.mime = sheet.type; + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + } + + if (env.relativeUrls) { + //todo - this relies on option being set on less object rather than being passed in as an option + // - need an originalRootpath + if (less.rootpath) { + newFileInfo.rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + env.contents[href] = data; // Updating content cache + env.paths = [hrefParts.path]; + env.currentFileInfo = newFileInfo; + + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + //TODO - there must be a better way? A generic less-to-css function that can both call error + //and removeNode where appropriate + //should also add tests + if (env.currentFileInfo.rootFilename === href) { + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } + } catch (e) { + callback(e, null, null, sheet); + } + }); + } catch (e) { + callback(e, null, null, sheet); + } + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, null, sheet); + }); +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss == null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + if (oldCss && keepOldCss === false) { + head.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] != undefined) { + error.push(template.replace(/\{line\}/, (parseInt(e.line) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0-beta.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0-beta.min.js new file mode 100644 index 000000000..4f0ee4f3a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0-beta.min.js @@ -0,0 +1,11 @@ +/* + * LESS - Leaner CSS v1.4.0 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache 2.0 License. + * + * @licence + */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a,f=[];while((a=w(this.extend))||(t=w(this.element))){a?f.push.apply(f,a):(f.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,f);f.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u,a;m(),t.dumpLineNumbers&&(a=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a,c;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){if(match=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=match[0].length-1,new i.Anonymous(match[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[];for(d=0;d1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e.filename||"input";e.filename=null;var i=n.replace(/[^\/\\]*$/,"");this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var p="{unable to calculate}",d="{unable to calculate}";try{p=u[0].selfSelectors[0].toCSS(),d=u[0].selector.toCSS()}catch(v){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+p+":extend("+d+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,match.pathIndex)),o.push(new e.Selector(a.elements.slice(s,match.index).concat([f]).concat(r.elements.slice(1)))),i=match.endPathIndex,s=match.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + options = options || {}; + var importError, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + var css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css, options.maxLineLen); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + callback(e); + } + else { + callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")) + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, delim, arg, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match, extend, extendList = []; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e) + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced, expression = []; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, currentFileInfo, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && currentFileInfo.currentDirectory) { + path = currentFileInfo.currentDirectory + path; + } + var sheetEnv = env.toSheet(path); + sheetEnv.processImports = false; + sheetEnv.currentFileInfo = currentFileInfo; + + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet(sheetEnv, + function (e, root, data, sheet, _, path) { + callback.call(null, e, root, path); + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + return values.value[index]; + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) mimetype += ';base64'; + } + else { + useBase64 = /;base64$/.test(mimetype) + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } else if (!this.env.silent) { + // if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn + console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + }, + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + type: "Color", + eval: function () { return this }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + + if (compress) { + color = color.split(''); + + // Convert color to short format + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) { + color = color[0] + color[2] + color[4]; + } else { + color = color.join(''); + } + } + + return '#' + color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + type: "Comment", + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function (env) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && !this.unit.isAngle()) { + return strValue; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + return strValue + this.unit.toCSS(env); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit, derivedConversions = {}; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + + toCSS: function (env) { + if (this.numerator.length >= 1) { + return this.numerator[0]; + } + if (this.denominator.length >= 1) { + return this.denominator[0]; + } + if ((!env || !env.strictUnits) && this.backupUnit) { + return this.backupUnit; + } + return ""; + }, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isAngle: function () { + return tree.UnitConversions.angle.hasOwnProperty(this.toCSS()); + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + toCSS: function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + }, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = []; + + for(i = 0; i < selectors.length; i++) { + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + var that = this; + + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined) { + this.css = !this.options.less; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + this.root = visitor.visit(this.root); + }, + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this.path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && !(path instanceof tree.URL)) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + toCSS: function () { return this.value; }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.ruleset = visitor.visit(this.ruleset); + }, + toCSS: function (env) { + var features = this.features.toCSS(env); + + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + toCSS: function () { return ""; }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval(new(tree.evalEnv)(env, + [this, frame].concat(mixinFrames))); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] + .concat(env.frames)))) { + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '-' + this.value.toCSS(env); + }, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + toCSS: function (env) { + var separator = this.isSpaced ? " " : ""; + return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS(); + } +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.variable) { return "" } + else { + try { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + } + }, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && env.strictMath === false) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + this.selectors = visitor.visit(this.selectors); + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + if (this.firstRoot && rule instanceof tree.Rule) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null}; + } + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + // Remove last semicolon + if (env.compress && rules.length) { + rule = rules[rules.length - 1]; + if (rule.charAt(rule.length - 1) === ';') { + rules[rules.length - 1] = rule.substring(0, rule.length - 1); + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = this.paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([], selector.extendList); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel, extendList; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extendList) { + this.elements = elements; + this.extendList = extendList || []; +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList) + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + })); + }, + toCSS: function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { this.name = name, this.index = index, this.currentFileInfo = currentFileInfo }; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function(a){if(a=='\\') a = '\/'; return '\\' + a}) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'strictImports', // option - + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'mime', // browser only - mime type for sheet import + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' = absolute path to the entry file + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = options.filename || "input"; + options.filename = null; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: options.rootpath || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + tree.parseEnv.prototype.toSheet = function (path) { + var env = new tree.parseEnv(this); + env.href = path; + //env.title = path; + env.type = this.mime; + return env; + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits' // whether units need to evaluate correctly + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + } +})(require('./tree'));(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + } + }; + +})(require('./tree'));(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode; + + if (!importNode.css) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && !evaldImportNode.css) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + this._importer.push(importNode.getPath(), importNode.currentFileInfo, function (e, root, imported) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (imported && !importNode.options.multiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + } else { + subFinish(); + } + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree'));(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.ruleset.root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree'));(function (tree) { + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex == 0 && hackstackElementIndex == 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator == '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + return false; + }, + extendSelector:function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)) + )); + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selector.elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree'));// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)(new less.tree.parseEnv(less)).parse(str, function (e, root) { + if (e) { + error(e, "session_cache"); + } else { + createCSS(root.toCSS(less), less.sheets[less.sheets.length - 1]); + } + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + var env = new less.tree.parseEnv(less); + env.filename = document.location.href.replace(/#.*$/, ''); + + new(less.Parser)(env).parse(styles[i].innerHTML || '', function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace("\\", "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var env; + var newFileInfo = { + relativeUrls: less.relativeUrls, + currentDirectory: hrefParts.path, + filename: href + }; + + if (sheet instanceof less.tree.parseEnv) { + env = new less.tree.parseEnv(sheet); + newFileInfo.entryPath = env.currentFileInfo.entryPath; + newFileInfo.rootpath = env.currentFileInfo.rootpath; + newFileInfo.rootFilename = env.currentFileInfo.rootFilename; + } else { + env = new less.tree.parseEnv(less); + env.mime = sheet.type; + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + } + + if (env.relativeUrls) { + //todo - this relies on option being set on less object rather than being passed in as an option + // - need an originalRootpath + if (less.rootpath) { + newFileInfo.rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + env.contents[href] = data; // Updating content cache + env.paths = [hrefParts.path]; + env.currentFileInfo = newFileInfo; + + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + //TODO - there must be a better way? A generic less-to-css function that can both call error + //and removeNode where appropriate + //should also add tests + if (env.currentFileInfo.rootFilename === href) { + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } + } catch (e) { + callback(e, null, null, sheet); + } + }); + } catch (e) { + callback(e, null, null, sheet); + } + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, null, sheet); + }); +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss == null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + if (oldCss && keepOldCss === false) { + head.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] != undefined) { + error.push(template.replace(/\{line\}/, (parseInt(e.line) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0.min.js new file mode 100644 index 000000000..4f0ee4f3a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.0.min.js @@ -0,0 +1,11 @@ +/* + * LESS - Leaner CSS v1.4.0 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache 2.0 License. + * + * @licence + */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a,f=[];while((a=w(this.extend))||(t=w(this.element))){a?f.push.apply(f,a):(f.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,f);f.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u,a;m(),t.dumpLineNumbers&&(a=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a,c;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){if(match=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=match[0].length-1,new i.Anonymous(match[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[];for(d=0;d1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e.filename||"input";e.filename=null;var i=n.replace(/[^\/\\]*$/,"");this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var p="{unable to calculate}",d="{unable to calculate}";try{p=u[0].selfSelectors[0].toCSS(),d=u[0].selector.toCSS()}catch(v){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+p+":extend("+d+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,match.pathIndex)),o.push(new e.Selector(a.elements.slice(s,match.index).concat([f]).concat(r.elements.slice(1)))),i=match.endPathIndex,s=match.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + options = options || {}; + var importError, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + var css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css, options.maxLineLen); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + callback(e); + } + else { + callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")) + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, delim, arg, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, extend, extendList = []; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e) + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced, expression = []; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, currentFileInfo, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && currentFileInfo.currentDirectory) { + path = currentFileInfo.currentDirectory + path; + } + var sheetEnv = env.toSheet(path); + sheetEnv.processImports = false; + sheetEnv.currentFileInfo = currentFileInfo; + + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet(sheetEnv, + function (e, root, data, sheet, _, path) { + callback.call(null, e, root, path); + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + return values.value[index]; + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) mimetype += ';base64'; + } + else { + useBase64 = /;base64$/.test(mimetype) + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } else if (!this.env.silent) { + // if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn + console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + }, + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + type: "Color", + eval: function () { return this }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + + if (compress) { + color = color.split(''); + + // Convert color to short format + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) { + color = color[0] + color[2] + color[4]; + } else { + color = color.join(''); + } + } + + return '#' + color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + type: "Comment", + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function (env) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && !this.unit.isAngle()) { + return strValue; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + return strValue + this.unit.toCSS(env); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit, derivedConversions = {}; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + + toCSS: function (env) { + if (this.numerator.length >= 1) { + return this.numerator[0]; + } + if (this.denominator.length >= 1) { + return this.denominator[0]; + } + if ((!env || !env.strictUnits) && this.backupUnit) { + return this.backupUnit; + } + return ""; + }, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isAngle: function () { + return tree.UnitConversions.angle.hasOwnProperty(this.toCSS()); + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + toCSS: function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + }, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i; + + for(i = 0; i < selectors.length; i++) { + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + var that = this; + + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined) { + this.css = !this.options.less; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + this.root = visitor.visit(this.root); + }, + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this.path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && !(path instanceof tree.URL)) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + toCSS: function () { return this.value; }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.ruleset = visitor.visit(this.ruleset); + }, + toCSS: function (env) { + var features = this.features.toCSS(env); + + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + toCSS: function () { return ""; }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval(new(tree.evalEnv)(env, + [this, frame].concat(mixinFrames))); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] + .concat(env.frames)))) { + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '-' + this.value.toCSS(env); + }, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + toCSS: function (env) { + var separator = this.isSpaced ? " " : ""; + return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS(); + } +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.variable) { return "" } + else { + try { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + } + }, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && env.strictMath === false) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + this.selectors = visitor.visit(this.selectors); + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + if (this.firstRoot && rule instanceof tree.Rule) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null}; + } + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + // Remove last semicolon + if (env.compress && rules.length) { + rule = rules[rules.length - 1]; + if (rule.charAt(rule.length - 1) === ';') { + rules[rules.length - 1] = rule.substring(0, rule.length - 1); + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = this.paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([], selector.extendList); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel, extendList; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extendList) { + this.elements = elements; + this.extendList = extendList || []; +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList) + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + })); + }, + toCSS: function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { this.name = name, this.index = index, this.currentFileInfo = currentFileInfo }; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function(a){if(a=='\\') a = '\/'; return '\\' + a}) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'strictImports', // option - + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'mime', // browser only - mime type for sheet import + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' = absolute path to the entry file + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + tree.parseEnv.prototype.toSheet = function (path) { + var env = new tree.parseEnv(this); + env.href = path; + //env.title = path; + env.type = this.mime; + return env; + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits' // whether units need to evaluate correctly + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + } +})(require('./tree'));(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + } + }; + +})(require('./tree'));(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode; + + if (!importNode.css) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && !evaldImportNode.css) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + this._importer.push(importNode.getPath(), importNode.currentFileInfo, function (e, root, imported) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (imported && !importNode.options.multiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + } else { + subFinish(); + } + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree'));(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.ruleset.root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree'));(function (tree) { + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex == 0 && hackstackElementIndex == 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator == '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + return false; + }, + extendSelector:function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement, + match; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)) + )); + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selector.elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree'));// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (var name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)(new less.tree.parseEnv(less)).parse(str, function (e, root) { + if (e) { + error(e, "session_cache"); + } else { + createCSS(root.toCSS(less), less.sheets[less.sheets.length - 1]); + } + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + var env = new less.tree.parseEnv(less); + env.filename = document.location.href.replace(/#.*$/, ''); + + new(less.Parser)(env).parse(styles[i].innerHTML || '', function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace("\\", "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var env; + var newFileInfo = { + relativeUrls: less.relativeUrls, + currentDirectory: hrefParts.path, + filename: href + }; + + if (sheet instanceof less.tree.parseEnv) { + env = new less.tree.parseEnv(sheet); + newFileInfo.entryPath = env.currentFileInfo.entryPath; + newFileInfo.rootpath = env.currentFileInfo.rootpath; + newFileInfo.rootFilename = env.currentFileInfo.rootFilename; + } else { + env = new less.tree.parseEnv(less); + env.mime = sheet.type; + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + } + + if (env.relativeUrls) { + //todo - this relies on option being set on less object rather than being passed in as an option + // - need an originalRootpath + if (less.rootpath) { + newFileInfo.rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + env.contents[href] = data; // Updating content cache + env.paths = [hrefParts.path]; + env.currentFileInfo = newFileInfo; + + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + //TODO - there must be a better way? A generic less-to-css function that can both call error + //and removeNode where appropriate + //should also add tests + if (env.currentFileInfo.rootFilename === href) { + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } + } catch (e) { + callback(e, null, null, sheet); + } + }); + } catch (e) { + callback(e, null, null, sheet); + } + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, null, sheet); + }); +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss == null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + if (oldCss && keepOldCss === false) { + head.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] != undefined) { + error.push(template.replace(/\{line\}/, (parseInt(e.line) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.1.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.1.min.js new file mode 100644 index 000000000..5aaea85d3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.1.min.js @@ -0,0 +1,11 @@ +/* + * LESS - Leaner CSS v1.4.1 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache 2.0 License. + * + * @licence + */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e=s.charAt(o);if(e===">"||e==="+"||e==="~"||e==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(e)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a=[];while((u=w(this.extend))||(t=w(this.element))){u?a.push.apply(a,u):(a.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,a);a.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u;m(),t.dumpLineNumbers&&(u=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var a=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(a.debugInfo=u),a}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){var e;if(e=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=e[0].length-1,new i.Anonymous(e[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[],n;for(n=0;n1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","syncImport","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e&&e.filename||"input",i=n.replace(/[^\/\\]*$/,"");e&&(e.filename=null),this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e&&e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","yuicompress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var d="{unable to calculate}",v="{unable to calculate}";try{d=u[0].selfSelectors[0].toCSS(),v=u[0].selector.toCSS()}catch(m){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+d+":extend("+v+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this,a;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,l.pathIndex)),o.push(new e.Selector(a.elements.slice(s,l.index).concat([f]).concat(r.elements.slice(1)))),i=l.endPathIndex,s=l.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + options = options || {}; + var importError, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + var css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css, options.maxLineLen); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + callback(e); + } + else { + callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")) + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, delim, arg, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, extend, extendList = []; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e) + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced, expression = []; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, currentFileInfo, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && currentFileInfo.currentDirectory) { + path = currentFileInfo.currentDirectory + path; + } + var sheetEnv = env.toSheet(path); + sheetEnv.processImports = false; + sheetEnv.currentFileInfo = currentFileInfo; + + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet(sheetEnv, + function (e, root, data, sheet, _, path) { + callback.call(null, e, root, path); + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + return values.value[index]; + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) mimetype += ';base64'; + } + else { + useBase64 = /;base64$/.test(mimetype) + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } else if (!this.env.silent) { + // if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn + console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + }, + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + type: "Color", + eval: function () { return this }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + + if (compress) { + color = color.split(''); + + // Convert color to short format + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) { + color = color[0] + color[2] + color[4]; + } else { + color = color.join(''); + } + } + + return '#' + color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + type: "Comment", + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function (env) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && !this.unit.isAngle()) { + return strValue; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + return strValue + this.unit.toCSS(env); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit, derivedConversions = {}; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + + toCSS: function (env) { + if (this.numerator.length >= 1) { + return this.numerator[0]; + } + if (this.denominator.length >= 1) { + return this.denominator[0]; + } + if ((!env || !env.strictUnits) && this.backupUnit) { + return this.backupUnit; + } + return ""; + }, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isAngle: function () { + return tree.UnitConversions.angle.hasOwnProperty(this.toCSS()); + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + toCSS: function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + }, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i; + + for(i = 0; i < selectors.length; i++) { + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + var that = this; + + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined) { + this.css = !this.options.less; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + this.root = visitor.visit(this.root); + }, + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this.path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && !(path instanceof tree.URL)) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + toCSS: function () { return this.value; }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.ruleset = visitor.visit(this.ruleset); + }, + toCSS: function (env) { + var features = this.features.toCSS(env); + + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + toCSS: function () { return ""; }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval(new(tree.evalEnv)(env, + [this, frame].concat(mixinFrames))); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] + .concat(env.frames)))) { + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '-' + this.value.toCSS(env); + }, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + toCSS: function (env) { + var separator = this.isSpaced ? " " : ""; + return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS(); + } +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.variable) { return "" } + else { + try { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + } + }, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + this.selectors = visitor.visit(this.selectors); + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + if (this.firstRoot && rule instanceof tree.Rule) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null}; + } + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + // Remove last semicolon + if (env.compress && rules.length) { + rule = rules[rules.length - 1]; + if (rule.charAt(rule.length - 1) === ';') { + rules[rules.length - 1] = rule.substring(0, rule.length - 1); + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = this.paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([], selector.extendList); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel, extendList; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extendList) { + this.elements = elements; + this.extendList = extendList || []; +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList) + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + })); + }, + toCSS: function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { this.name = name, this.index = index, this.currentFileInfo = currentFileInfo }; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function(a){if(a=='\\') a = '\/'; return '\\' + a}) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'strictImports', // option - + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'mime', // browser only - mime type for sheet import + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' = absolute path to the entry file + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + tree.parseEnv.prototype.toSheet = function (path) { + var env = new tree.parseEnv(this); + env.href = path; + //env.title = path; + env.type = this.mime; + return env; + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits' // whether units need to evaluate correctly + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + } +})(require('./tree'));(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + } + }; + +})(require('./tree'));(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode; + + if (!importNode.css) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && !evaldImportNode.css) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + this._importer.push(importNode.getPath(), importNode.currentFileInfo, function (e, root, imported) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (imported && !importNode.options.multiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + } else { + subFinish(); + } + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree'));(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.ruleset.root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree'));(function (tree) { + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex == 0 && hackstackElementIndex == 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator == '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + return false; + }, + extendSelector:function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement, + match; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)) + )); + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selector.elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree'));// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (var name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)(new less.tree.parseEnv(less)).parse(str, function (e, root) { + if (e) { + error(e, "session_cache"); + } else { + createCSS(root.toCSS(less), less.sheets[less.sheets.length - 1]); + } + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + var env = new less.tree.parseEnv(less); + env.filename = document.location.href.replace(/#.*$/, ''); + + new(less.Parser)(env).parse(styles[i].innerHTML || '', function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var env; + var newFileInfo = { + relativeUrls: less.relativeUrls, + currentDirectory: hrefParts.path, + filename: href + }; + + if (sheet instanceof less.tree.parseEnv) { + env = new less.tree.parseEnv(sheet); + newFileInfo.entryPath = env.currentFileInfo.entryPath; + newFileInfo.rootpath = env.currentFileInfo.rootpath; + newFileInfo.rootFilename = env.currentFileInfo.rootFilename; + } else { + env = new less.tree.parseEnv(less); + env.mime = sheet.type; + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + } + + if (env.relativeUrls) { + //todo - this relies on option being set on less object rather than being passed in as an option + // - need an originalRootpath + if (less.rootpath) { + newFileInfo.rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + env.contents[href] = data; // Updating content cache + env.paths = [hrefParts.path]; + env.currentFileInfo = newFileInfo; + + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + //TODO - there must be a better way? A generic less-to-css function that can both call error + //and removeNode where appropriate + //should also add tests + if (env.currentFileInfo.rootFilename === href) { + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } + } catch (e) { + callback(e, null, null, sheet); + } + }); + } catch (e) { + callback(e, null, null, sheet); + } + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, null, sheet); + }); +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss == null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + if (oldCss && keepOldCss === false) { + head.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] != undefined) { + error.push(template.replace(/\{line\}/, (parseInt(e.line) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} +})(window); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.2.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.2.min.js new file mode 100644 index 000000000..e4a34ff25 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.4.2.min.js @@ -0,0 +1,11 @@ +/* + * LESS - Leaner CSS v1.4.2 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache 2.0 License. + * + * @licence + */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e=s.charAt(o);if(e===">"||e==="+"||e==="~"||e==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(e)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a=[];while((u=w(this.extend))||(t=w(this.element))){u?a.push.apply(a,u):(a.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,a);a.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u;m(),t.dumpLineNumbers&&(u=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var a=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(a.debugInfo=u),a}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){var e;if(e=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=e[0].length-1,new i.Anonymous(e[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[],n;for(n=0;n1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","syncImport","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e&&e.filename||"input",i=n.replace(/[^\/\\]*$/,"");e&&(e.filename=null),this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e&&e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","yuicompress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var d="{unable to calculate}",v="{unable to calculate}";try{d=u[0].selfSelectors[0].toCSS(),v=u[0].selector.toCSS()}catch(m){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+d+":extend("+v+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this,a;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,l.pathIndex)),o.push(new e.Selector(a.elements.slice(s,l.index).concat([f]).concat(r.elements.slice(1)))),i=l.endPathIndex,s=l.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d + * Licensed under the Apache v2 License. + * + * @licence + */ + + + +(function (window, undefined) {// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + + +if (typeof(window.less) === 'undefined' || typeof(window.less.nodeType) !== 'undefined') { window.less = {}; } +less = window.less; +tree = window.less.tree = {}; +less.mode = 'browser'; + +var less, tree; + +// Node.js does not have a header file added which defines less +if (less === undefined) { + less = exports; + tree = require('./tree'); + less.mode = 'node'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser, + rootFilename = env && env.filename; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed around by reference. + if (!(env instanceof tree.parseEnv)) { + env = new tree.parseEnv(env); + } + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, currentFileInfo, importOptions, callback) { + var parserImports = this; + this.queue.push(path); + + var fileParsedFunc = function (e, root, fullPath) { + parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue + + var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename; + + parserImports.files[fullPath] = root; // Store the root + + if (e && !parserImports.error) { parserImports.error = e; } + + callback(e, root, importedPreviously, fullPath); + }; + + if (less.Parser.importer) { + less.Parser.importer(path, currentFileInfo, fileParsedFunc, env); + } else { + less.Parser.fileLoader(path, currentFileInfo, function(e, contents, fullPath, newFileInfo) { + if (e) {fileParsedFunc(e); return;} + + var newEnv = new tree.parseEnv(env); + + newEnv.currentFileInfo = newFileInfo; + newEnv.processImports = false; + newEnv.contents[fullPath] = contents; + + if (currentFileInfo.reference || importOptions.reference) { + newFileInfo.reference = true; + } + + if (importOptions.inline) { + fileParsedFunc(null, contents, fullPath); + } else { + new(less.Parser)(newEnv).parse(contents, function (e, root) { + fileParsedFunc(e, root, fullPath); + }); + } + }, env); + } + } + }; + + function save() { temp = chunks[j], memo = i, current = i; } + function restore() { chunks[j] = temp, i = memo, current = i; } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, length; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break; } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return tok.test(chunks[j]); + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, inputStream) { + var n = index + 1, + line = null, + column = -1; + + while (--n >= 0 && inputStream.charAt(n) !== '\n') { + column++; + } + + if (typeof index === 'number') { + line = (inputStream.slice(0, index).match(/\n/g) || "").length; + } + + return { + line: line, + column: column + }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + callLine = e.call && getLocation(e.call, input).line, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = callLine + 1; + this.callExtract = lines[callLine]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, line, lines, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + parser.imports.contents[env.currentFileInfo.filename] = input; + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': + if (!inParam) { + level++; + chunk.push(c); + break; + } + /* falls through */ + case '}': + if (!inParam) { + level--; + chunk.push(c); + chunks[++j] = chunk = []; + break; + } + /* falls through */ + case '(': + if (!inParam) { + inParam = true; + chunk.push(c); + break; + } + /* falls through */ + case ')': + if (inParam) { + inParam = false; + chunk.push(c); + break; + } + /* falls through */ + default: + chunk.push(c); + } + + i++; + } + if (level !== 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join(''); }); + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + return function (options, variables) { + options = options || {}; + var evaldRoot, + css, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, null, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + new(tree.toCSSVisitor)({compress: Boolean(options.compress)}) + .run(evaldRoot); + + if (options.sourceMap) { + evaldRoot = new tree.sourceMapOutput( + { + writeSourceMap: options.writeSourceMap, + rootNode: evaldRoot, + contentsMap: parser.imports.contents, + sourceMapFilename: options.sourceMapFilename, + outputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath, + outputSourceFiles: options.outputSourceFiles, + sourceMapGenerator: options.sourceMapGenerator + }); + } + + css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.cleancss && less.mode === 'node') { + return require('clean-css').process(css); + } else if (options.compress) { + return css.replace(/(^(\s)+)|((\s)+$)/g, ""); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + var loc = getLocation(i, input); + lines = input.split('\n'); + line = loc.line + 1; + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: loc.column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + return callback(e); + } + else { + return callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + return finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') { return; } + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true, i, env.currentFileInfo); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment, false, i, env.currentFileInfo); + } + }, + + comments: function () { + var comment, comments = []; + + while(comment = $(this.comment)) { + comments.push(comment); + } + + return comments; + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true; } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { return; } + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + var color = tree.Color.fromKeyword(k); + if (color) { + return color; + } + return new(tree.Keyword)(k); + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) { return; } + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null; } + else { i += name.length; } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { + break; + } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) { + return; + } + + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + /*jshint eqnull:true */ + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) { + return; + } + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings + if (input.charAt(j) !== '`') { return; } + if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) { + error("You are using JavaScript, which has been disabled."); + } + + if (e) { $('~'); } + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")); + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return; } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i, env.currentFileInfo)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comments); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) { + return; + } + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comments); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) { return; } + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i, env.currentFileInfo); } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++; } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + // + // A CSS selector (see selector below) + // with less extensions e.g. the ability to extend and guard + // + lessSelector: function () { + return this.selector(true); + }, + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function (isLess) { + var e, elements = [], c, extend, extendList = [], when, condition; + + while ((isLess && (extend = $(this.extend))) || (isLess && (when = $(/^when/))) || (e = $(this.element))) { + if (when) { + condition = expect(this.conditions, 'expected condition'); + } else if (condition) { + error("CSS guard can only be used at the end of selector"); + } else if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e); + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { + break; + } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList, condition, i, env.currentFileInfo); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var key, val, op; + + if (! $('[')) { return; } + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[0-9]+%/) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + while (s = $(this.lessSelector)) { + selectors.push(s); + $(this.comments); + if (! $(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + $(this.comments); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) { + ruleset.debugInfo = debugInfo; + } + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, merge = false; + save(); + + if (c === '.' || c === '#' || c === '&') { return; } + + if (name = $(this.variable) || $(this.ruleProperty)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + + important = $(this.important); + if (name[name.length-1] === "+") { + merge = true; + name = name.substr(0, name.length - 1); + } + + if (value && $(this.end)) { + return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break; } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once|inline|reference)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = ($(this.entities.keyword) || $(this.entities.variable))) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null; } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break; } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break; } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + media.debugInfo = debugInfo; + } + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression, identifier; + + if (input.charAt(i) !== '@') { return; } + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) { return; } + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@host": + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + identifier = ($(/^[^{]+/) || '').trim(); + if (identifier) { + name += " " + identifier; + } + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules, i, env.currentFileInfo); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = []; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while (peek(/^,\s*(not\s*)?\(/) && $(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true; } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|<=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-'); } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = []; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + }, + ruleProperty: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/)) { + return name[1] + (name[2] || ""); + } + } + } + }; +}; + + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; } + else if (h * 2 < 1) { return m2; } + else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; } + else { return m1; } + } + + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + // filter: saturate(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + /*jshint loopfunc:true */ + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + if(!(val instanceof tree.Dimension)) { + throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") }; + } + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + /*jshint eqnull:true */ + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + _minmax: function (isMin, args) { + args = Array.prototype.slice.call(args); + switch(args.length) { + case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 1: return args[0]; + } + var i, j, current, currentUnified, referenceUnified, unit, + order = [], // elems only contains original argument values. + values = {}; // key is the unit.toString() for unified tree.Dimension values, + // value is the index into the order array. + for (i = 0; i < args.length; i++) { + current = args[i]; + if (!(current instanceof tree.Dimension)) { + order.push(current); + continue; + } + currentUnified = current.unify(); + unit = currentUnified.unit.toString(); + j = values[unit]; + if (j === undefined) { + values[unit] = order.length; + order.push(current); + continue; + } + referenceUnified = order[j].unify(); + if ( isMin && currentUnified.value < referenceUnified.value || + !isMin && currentUnified.value > referenceUnified.value) { + order[j] = current; + } + } + if (order.length == 1) { + return order[0]; + } + args = order.map(function (a) { return a.toCSS(this.env); }) + .join(this.env.compress ? "," : ", "); + return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")"); + }, + min: function () { + return this._minmax(true, arguments); + }, + max: function () { + return this._minmax(false, arguments); + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + var colorCandidate = n.value, + returnColor; + returnColor = tree.Color.fromKeyword(colorCandidate); + if (returnColor) { + return returnColor; + } + if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) { + return new(tree.Color)(colorCandidate.slice(1)); + } + throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" }; + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + // handle non-array values as an array of length 1 + // return 'undefined' if index is invalid + return Array.isArray(values.value) + ? values.value[index] : Array(values)[index]; + }, + length: function(values) { + var n = Array.isArray(values.value) ? values.value.length : 1; + return new tree.Dimension(n); + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) { mimetype += ';base64'; } + } + else { + useBase64 = /;base64$/.test(mimetype); + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + }, + + "svg-gradient": function(direction) { + + function throwArgumentDescriptor() { + throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" }; + } + + if (arguments.length < 3) { + throwArgumentDescriptor(); + } + var stops = Array.prototype.slice.call(arguments, 1), + gradientDirectionSvg, + gradientType = "linear", + rectangleDimension = 'x="0" y="0" width="1" height="1"', + useBase64 = true, + renderEnv = {compress: false}, + returner, + directionValue = direction.toCSS(renderEnv), + i, color, position, positionValue, alpha; + + switch (directionValue) { + case "to bottom": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; + break; + case "to right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; + break; + case "to bottom right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; + break; + case "to top right": + gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; + break; + case "ellipse": + case "ellipse at center": + gradientType = "radial"; + gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; + rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; + break; + default: + throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" }; + } + returner = '' + + '' + + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; + + for (i = 0; i < stops.length; i+= 1) { + if (stops[i].value) { + color = stops[i].value[0]; + position = stops[i].value[1]; + } else { + color = stops[i]; + position = undefined; + } + + if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) { + throwArgumentDescriptor(); + } + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + alpha = color.alpha; + returner += ''; + } + returner += '' + + ''; + + if (useBase64) { + // only works in node, needs interface to what is supported in environment + try { + returner = new Buffer(returner).toString('base64'); + } catch(e) { + useBase64 = false; + } + } + + returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'"; + return new(tree.URL)(new(tree.Anonymous)(returner)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + /*jshint eqnull:true */ + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); + +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); + +(function (tree) { + +tree.debugInfo = function(env, ctx, lineSeperator) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) { + if (a == '\\') { + a = '\/'; + } + return '\\' + a; + }) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r; } + } + return null; +}; + +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +tree.toCSS = function (env) { + var strs = []; + this.genCSS(env, { + add: function(chunk, fileInfo, index) { + strs.push(chunk); + }, + isEmpty: function () { + return strs.length === 0; + } + }); + return strs.join(''); +}; + +tree.outputRuleset = function (env, output, rules) { + output.add((env.compress ? '{' : ' {\n')); + env.tabLevel = (env.tabLevel || 0) + 1; + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + for(var i = 0; i < rules.length; i++) { + output.add(tabRuleStr); + rules[i].genCSS(env, output); + output.add(env.compress ? '' : '\n'); + } + env.tabLevel--; + output.add(tabSetStr + "}"); +}; + +})(require('./tree')); + +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); } + return this; + }, + genCSS: function (env, output) { + output.add("alpha(opacity="); + + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + + output.add(")"); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Anonymous = function (string, index, currentFileInfo, mapLines) { + this.value = string.value || string; + this.index = index; + this.mapLines = mapLines; + this.currentFileInfo = currentFileInfo; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + eval: function () { return this; }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + }, + genCSS: function (env, output) { + output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add(this.key + '='); + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + /*jshint eqnull:true */ + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + return new tree.Call(this.name, args, this.index, this.currentFileInfo); + }, + + genCSS: function (env, output) { + output.add(this.name + "(", this.currentFileInfo, this.index); + + for(var i = 0; i < this.args.length; i++) { + this.args[i].genCSS(env, output); + if (i + 1 < this.args.length) { + output.add(", "); + } + } + + output.add(")"); + }, + + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; + +var transparentKeyword = "transparent"; + +tree.Color.prototype = { + type: "Color", + eval: function () { return this; }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + if (this.alpha < 1.0) { + if (this.alpha === 0 && this.isTransparentKeyword) { + return transparentKeyword; + } + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.toRGB(); + + if (compress) { + var splitcolor = color.split(''); + + // Convert color to short format + if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) { + color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5]; + } + } + + return color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toRGB: function () { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + +tree.Color.fromKeyword = function(keyword) { + if (tree.colors.hasOwnProperty(keyword)) { + // detect named color + return new(tree.Color)(tree.colors[keyword].slice(1)); + } + if (keyword === transparentKeyword) { + var transparent = new(tree.Color)([0, 0, 0], 0); + transparent.isTransparentKeyword = true; + return transparent; + } +}; + + +})(require('../tree')); + +(function (tree) { + +tree.Comment = function (value, silent, index, currentFileInfo) { + this.value = value; + this.silent = !!silent; + this.currentFileInfo = currentFileInfo; +}; +tree.Comment.prototype = { + type: "Comment", + genCSS: function (env, output) { + if (this.debugInfo) { + output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index); + } + output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n + }, + toCSS: tree.toCSS, + isSilent: function(env) { + var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced), + isCompressed = env.compress && !this.value.match(/^\/\*!/); + return this.silent || isReference || isCompressed; + }, + eval: function () { return this; }, + markReferenced: function () { + this.isReferenced = true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<' || op === '<='; + case 0: return op === '=' || op === '>=' || op === '=<' || op === '<='; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); + +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + genCSS: function (env, output) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && this.unit.isLength()) { + output.add(strValue); + return; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + output.add(strValue); + this.unit.genCSS(env, output); + }, + toCSS: tree.toCSS, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + /*jshint noempty:false */ + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, targetUnit, derivedConversions = {}, applyUnit; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + applyUnit = function (atomicUnit, denominator) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(applyUnit); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + genCSS: function (env, output) { + if (this.numerator.length >= 1) { + output.add(this.numerator[0]); + } else + if (this.denominator.length >= 1) { + output.add(this.denominator[0]); + } else + if ((!env || !env.strictUnits) && this.backupUnit) { + output.add(this.backupUnit); + } + }, + toCSS: tree.toCSS, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isLength: function () { + return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/)); + }, + + isEmpty: function () { + return this.numerator.length === 0 && this.denominator.length === 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length === 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, result = {}, mapUnit; + + mapUnit = function (atomicUnit) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }; + + for (var groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(mapUnit); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Directive = function (name, value, index, currentFileInfo) { + this.name = name; + + if (Array.isArray(value)) { + this.rules = [new(tree.Ruleset)([], value)]; + this.rules[0].allowImports = true; + } else { + this.value = value; + } + this.currentFileInfo = currentFileInfo; + +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.rules = visitor.visit(this.rules); + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name, this.currentFileInfo, this.index); + if (this.rules) { + tree.outputRuleset(env, output, this.rules); + } else { + output.add(' '); + this.value.genCSS(env, output); + output.add(';'); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var evaldDirective = this; + if (this.rules) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo); + evaldDirective.rules = [this.rules[0].eval(env)]; + evaldDirective.rules[0].root = true; + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + markReferenced: function () { + var i, rules; + this.isReferenced = true; + if (this.rules) { + rules = this.rules[0].rules; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Element = function (combinator, value, index, currentFileInfo) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index, + this.currentFileInfo); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env), this.currentFileInfo, this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value === '' && this.combinator.value.charAt(0) === '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + _outputMap: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : ' + ', + '~' : ' ~ ', + '>' : ' > ', + '|' : '|' + }, + _outputMapCompressed: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : '+', + '~' : '~', + '>' : '>', + '|' : '|' + }, + genCSS: function (env, output) { + output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + genCSS: function (env, output) { + for(var i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add(" "); + } + } + }, + toCSS: tree.toCSS, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i, + selectorElements; + + for(i = 0; i < selectors.length; i++) { + selectorElements = selectors[i].elements; + // duplicate the logic in genCSS function inside the selector node. + // future TODO - move both logics into the selector joiner visitor + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + selectorElements[0].combinator.value = ' '; + } + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); + +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined || this.options.inline) { + this.css = !this.options.less || this.options.inline; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + if (!this.options.inline) { + this.root = visitor.visit(this.root); + } + }, + genCSS: function (env, output) { + if (this.css) { + output.add("@import ", this.currentFileInfo, this.index); + this.path.genCSS(env, output); + if (this.features) { + output.add(" "); + this.features.genCSS(env, output); + } + output.add(';'); + } + }, + toCSS: tree.toCSS, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + + if (!(path instanceof tree.URL)) { + if (rootpath) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + path.value = env.normalizePath(path.value); + } + + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.options.inline) { + //todo needs to reference css file not import + var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true); + return this.features ? new(tree.Media)([contents], this.features.value) : [contents]; + } else if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + /*jshint loopfunc:true */ + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Keyword = function (value) { this.value = value; }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); + +(function (tree) { + +tree.Media = function (value, features, index, currentFileInfo) { + this.index = index; + this.currentFileInfo = currentFileInfo; + + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.rules = [new(tree.Ruleset)(selectors, value)]; + this.rules[0].allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.rules = visitor.visit(this.rules); + }, + genCSS: function (env, output) { + output.add('@media ', this.currentFileInfo, this.index); + this.features.genCSS(env, output); + tree.outputRuleset(env, output, this.rules); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], [], this.index, this.currentFileInfo); + if(this.debugInfo) { + this.rules[0].debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.rules[0]); + media.rules = [this.rules[0].eval(env)]; + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env); + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', this.index, this.currentFileInfo); + return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)]; + }, + markReferenced: function () { + var i, rules = this.rules[0].rules; + this.isReferenced = true; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])]; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + if (!(mixin instanceof tree.mixin.Definition)) { + mixin = new tree.mixin.Definition("", [], mixin.rules, null, false); + mixin.originalRuleset = mixins[m].originalRuleset || mixins[m]; + } + //if (this.important) { + // isImportant = env.isImportant; + // env.isImportant = true; + //} + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + //if (this.important) { + // env.isImportant = isImportant; + //} + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + if (!this.currentFileInfo || !this.currentFileInfo.reference) { + for (i = 0; i < rules.length; i++) { + rule = rules[i]; + if (rule.markReferenced) { + rule.markReferenced(); + } + } + } + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1; } + else { return count; } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + /*jshint boss:true */ + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) { continue; } + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + rules, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules); + ruleset.originalRuleset = this; + ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames))); + if (important) { + ruleset = this.parent.makeImportant.apply(ruleset); + } + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables + .concat(this.frames) // the parent namespace/mixin frames + .concat(env.frames)))) { // the current environment frames + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (! this.variadic) { + if (argsLength < this.required) { return false; } + if (argsLength > this.params.length) { return false; } + } else { + if (argsLength < (this.required - 1)) { return false; } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('-'); + this.value.genCSS(env, output); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + genCSS: function (env, output) { + this.operands[0].genCSS(env, output); + if (this.isSpaced) { + output.add(" "); + } + output.add(this.op); + if (this.isSpaced) { + output.add(" "); + } + this.operands[1].genCSS(env, output); + }, + toCSS: tree.toCSS +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('('); + this.value.genCSS(env, output); + output.add(')'); + }, + toCSS: tree.toCSS, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + genCSS: function (env, output) { + if (!this.escaped) { + output.add(this.quote, this.currentFileInfo, this.index); + } + output.add(this.value); + if (!this.escaped) { + output.add(this.quote); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (name.charAt(0) === '@'); +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index); + try { + this.value.genCSS(env, output); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index); + }, + toCSS: tree.toCSS, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.merge, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.merge, + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + if (this.paths) { + for(var i = 0; i < this.paths.length; i++) { + this.paths[i] = visitor.visit(this.paths[i]); + } + } else { + this.selectors = visitor.visit(this.selectors); + } + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env); }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + var rule; + var i; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + /*jshint loopfunc:true */ + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (i = 0; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + matchCondition: function (args, env) { + var lastSelector = this.selectors[this.selectors.length-1]; + if (lastSelector.condition && + !lastSelector.condition.eval( + new(tree.evalEnv)(env, + env.frames))) { + return false; + } + return true; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables; } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key]; } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + genCSS: function (env, output) { + var i, j, + ruleNodes = [], + rulesetNodes = [], + debugInfo, // Line number debugging + rule, + firstRuleset = true, + path; + + env.tabLevel = (env.tabLevel || 0); + + if (!this.root) { + env.tabLevel++; + } + + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + + for (i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + if (rule.rules || (rule instanceof tree.Media) || rule instanceof tree.Directive || (this.root && rule instanceof tree.Comment)) { + rulesetNodes.push(rule); + } else { + ruleNodes.push(rule); + } + } + + // If this is the root node, we don't render + // a selector, or {}. + if (!this.root) { + debugInfo = tree.debugInfo(env, this, tabSetStr); + + if (debugInfo) { + output.add(debugInfo); + output.add(tabSetStr); + } + + for(i = 0; i < this.paths.length; i++) { + path = this.paths[i]; + env.firstSelector = true; + for(j = 0; j < path.length; j++) { + path[j].genCSS(env, output); + env.firstSelector = false; + } + if (i + 1 < this.paths.length) { + output.add(env.compress ? ',' : (',\n' + tabSetStr)); + } + } + + output.add((env.compress ? '{' : ' {\n') + tabRuleStr); + } + + // Compile rules and rulesets + for (i = 0; i < ruleNodes.length; i++) { + rule = ruleNodes[i]; + + // @page{ directive ends up with root elements inside it, a mix of rules and rulesets + // In this instance we do not know whether it is the last property + if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) { + env.lastRule = true; + } + + if (rule.genCSS) { + rule.genCSS(env, output); + } else if (rule.value) { + output.add(rule.value.toString()); + } + + if (!env.lastRule) { + output.add(env.compress ? '' : ('\n' + tabRuleStr)); + } else { + env.lastRule = false; + } + } + + if (!this.root) { + output.add((env.compress ? '}' : '\n' + tabSetStr + '}')); + env.tabLevel--; + } + + for (i = 0; i < rulesetNodes.length; i++) { + if (ruleNodes.length && firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + if (!firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + firstRuleset = false; + rulesetNodes[i].genCSS(env, output); + } + + if (!output.isEmpty() && !env.compress && this.firstRoot) { + output.add('\n'); + } + }, + + toCSS: tree.toCSS, + + markReferenced: function () { + for (var s = 0; s < this.selectors.length; s++) { + this.selectors[s].markReferenced(); + } + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for (i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for (j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length === 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0, el.index, el.currentFileInfo)); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for (k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = selector.createDerived([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for (i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length === 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for (i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); + +(function (tree) { + +tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) { + this.elements = elements; + this.extendList = extendList || []; + this.condition = condition; + this.currentFileInfo = currentFileInfo || {}; + this.isReferenced = isReferenced; + if (!condition) { + this.evaldCondition = true; + } +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList); + this.condition = visitor.visit(this.condition); + }, + createDerived: function(elements, extendList, evaldCondition) { + /*jshint eqnull:true */ + evaldCondition = evaldCondition != null ? evaldCondition : this.evaldCondition; + var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced); + newSelector.evaldCondition = evaldCondition; + return newSelector; + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + var evaldCondition = this.condition && this.condition.eval(env); + + return this.createDerived(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + }), evaldCondition); + }, + genCSS: function (env, output) { + var i, element; + if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") { + output.add(' ', this.currentFileInfo, this.index); + } + if (!this._css) { + //TODO caching? speed comparison? + for(i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(env, output); + } + } + }, + toCSS: tree.toCSS, + markReferenced: function () { + this.isReferenced = true; + }, + getIsReferenced: function() { + return !this.currentFileInfo.reference || this.isReferenced; + }, + getIsOutput: function() { + return this.evaldCondition; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + eval: function () { return this; } +}; + +})(require('../tree')); + +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add("url("); + this.value.genCSS(env, output); + output.add(")"); + }, + toCSS: tree.toCSS, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + val.value = ctx.normalizePath(val.value); + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + genCSS: function (env, output) { + var i; + for(i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i+1 < this.value.length) { + output.add((env && env.compress) ? ',' : ', '); + } + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { + this.name = name; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') === 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); + +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'rootpath', // option - rootpath to append to URL's + 'strictImports', // option - + 'insecure', // option - whether to allow imports from insecure ssl hosts + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true + 'mime', // browser only - mime type for sheet import + 'useFileCache', // browser only - whether to use the per file session cache + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' - absolute path to the entry file + // 'reference' - whether the file should not be output and only output parts that are referenced + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'cleancss', // whether to compress with clean-css + 'sourceMap', // whether to output a source map + 'importMultiple'// whether we are currently importing multiple copies + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + tree.evalEnv.prototype.normalizePath = function( path ) { + var + segments = path.split("/").reverse(), + segment; + + path = []; + while (segments.length !== 0 ) { + segment = segments.pop(); + switch( segment ) { + case ".": + break; + case "..": + if ((path.length === 0) || (path[path.length - 1] === "..")) { + path.push( segment ); + } else { + path.pop(); + } + break; + default: + path.push( segment ); + break; + } + } + + return path.join("/"); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + evald = this.flatten(evald); + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + }, + doAccept: function (node) { + node.accept(this); + }, + flatten: function(arr, master) { + return arr.reduce(this.flattenReduce.bind(this), master || []); + }, + flattenReduce: function(sum, element) { + if (element instanceof Array) { + sum = this.flatten(element, sum); + } else { + sum.push(element); + } + return sum; + } + }; + +})(require('./tree')); +(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode, + inlineCSS = importNode.options.inline; + + if (!importNode.css || inlineCSS) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + + if (importNode.options.multiple) { + env.importMultiple = true; + } + + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + + if (imported && !env.importMultiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + importNode.importedFilename = fullPath; + if (!inlineCSS && !importNode.skip) { + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + return; + } + } + + subFinish(); + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree')); +(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.selectors = rulesetNode.selectors.filter(function(selector) { return selector.getIsOutput(); }); + if (rulesetNode.selectors.length === 0) { + rulesetNode.rules.length = 0; + } + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree')); +(function (tree) { + tree.toCSSVisitor = function(env) { + this._visitor = new tree.visitor(this); + this._env = env; + }; + + tree.toCSSVisitor.prototype = { + isReplacing: true, + run: function (root) { + return this._visitor.visit(root); + }, + + visitRule: function (ruleNode, visitArgs) { + if (ruleNode.variable) { + return []; + } + return ruleNode; + }, + + visitMixinDefinition: function (mixinNode, visitArgs) { + return []; + }, + + visitExtend: function (extendNode, visitArgs) { + return []; + }, + + visitComment: function (commentNode, visitArgs) { + if (commentNode.isSilent(this._env)) { + return []; + } + return commentNode; + }, + + visitMedia: function(mediaNode, visitArgs) { + mediaNode.accept(this._visitor); + visitArgs.visitDeeper = false; + + if (!mediaNode.rules.length) { + return []; + } + return mediaNode; + }, + + visitDirective: function(directiveNode, visitArgs) { + if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) { + return []; + } + if (directiveNode.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (this.charset) { + if (directiveNode.debugInfo) { + var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n"); + comment.debugInfo = directiveNode.debugInfo; + return this._visitor.visit(comment); + } + return []; + } + this.charset = true; + } + return directiveNode; + }, + + checkPropertiesInRoot: function(rules) { + var ruleNode; + for(var i = 0; i < rules.length; i++) { + ruleNode = rules[i]; + if (ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null}; + } + } + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var rule, rulesets = []; + if (rulesetNode.firstRoot) { + this.checkPropertiesInRoot(rulesetNode.rules); + } + if (! rulesetNode.root) { + + rulesetNode.paths = rulesetNode.paths + .filter(function(p) { + var i; + if (p[0].elements[0].combinator.value === ' ') { + p[0].elements[0].combinator = new(tree.Combinator)(''); + } + for(i = 0; i < p.length; i++) { + if (p[i].getIsReferenced() && p[i].getIsOutput()) { + return true; + } + return false; + } + }); + + // Compile rules and rulesets + for (var i = 0; i < rulesetNode.rules.length; i++) { + rule = rulesetNode.rules[i]; + + if (rule.rules) { + // visit because we are moving them out from being a child + rulesets.push(this._visitor.visit(rule)); + rulesetNode.rules.splice(i, 1); + i--; + continue; + } + } + // accept the visitor to remove rules and refactor itself + // then we can decide now whether we want it or not + if (rulesetNode.rules.length > 0) { + rulesetNode.accept(this._visitor); + } + visitArgs.visitDeeper = false; + + this._mergeRules(rulesetNode.rules); + this._removeDuplicateRules(rulesetNode.rules); + + // now decide whether we keep the ruleset + if (rulesetNode.rules.length > 0 && rulesetNode.paths.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } else { + rulesetNode.accept(this._visitor); + visitArgs.visitDeeper = false; + if (rulesetNode.firstRoot || rulesetNode.rules.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } + if (rulesets.length === 1) { + return rulesets[0]; + } + return rulesets; + }, + + _removeDuplicateRules: function(rules) { + // remove duplicates + var ruleCache = {}, + ruleList, rule, i; + for(i = rules.length - 1; i >= 0 ; i--) { + rule = rules[i]; + if (rule instanceof tree.Rule) { + if (!ruleCache[rule.name]) { + ruleCache[rule.name] = rule; + } else { + ruleList = ruleCache[rule.name]; + if (ruleList instanceof tree.Rule) { + ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)]; + } + var ruleCSS = rule.toCSS(this._env); + if (ruleList.indexOf(ruleCSS) !== -1) { + rules.splice(i, 1); + } else { + ruleList.push(ruleCSS); + } + } + } + } + }, + + _mergeRules: function (rules) { + var groups = {}, + parts, + rule, + key; + + for (var i = 0; i < rules.length; i++) { + rule = rules[i]; + + if ((rule instanceof tree.Rule) && rule.merge) { + key = [rule.name, + rule.important ? "!" : ""].join(","); + + if (!groups[key]) { + parts = groups[key] = []; + } else { + rules.splice(i--, 1); + } + + parts.push(rule); + } + } + + Object.keys(groups).map(function (k) { + parts = groups[k]; + + if (parts.length > 1) { + rule = parts[0]; + + rule.value = new (tree.Value)(parts.map(function (p) { + return p.value; + })); + } + }); + } + }; + +})(require('./tree')); +(function (tree) { + /*jshint loopfunc:true */ + + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + rulesetNode.extendOnEveryPath = true; + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (rulesetNode.extendOnEveryPath || selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator === '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + elementValue1 = elementValue1.value; + elementValue2 = elementValue2.value; + if (elementValue1 instanceof tree.Selector) { + if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) { + return false; + } + for(var i = 0; i currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + newElements = selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)); + + if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) { + path[path.length - 1].elements = + path[path.length - 1].elements.concat(newElements); + } else { + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + newElements + )); + } + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.sourceMapOutput = function (options) { + this._css = []; + this._rootNode = options.rootNode; + this._writeSourceMap = options.writeSourceMap; + this._contentsMap = options.contentsMap; + this._sourceMapFilename = options.sourceMapFilename; + this._outputFilename = options.outputFilename; + this._sourceMapBasepath = options.sourceMapBasepath; + this._sourceMapRootpath = options.sourceMapRootpath; + this._outputSourceFiles = options.outputSourceFiles; + this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator; + + if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') { + this._sourceMapRootpath += '/'; + } + + this._lineNumber = 0; + this._column = 0; + }; + + tree.sourceMapOutput.prototype.normalizeFilename = function(filename) { + if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { + filename = filename.substring(this._sourceMapBasepath.length); + if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { + filename = filename.substring(1); + } + } + return (this._sourceMapRootpath || "") + filename.replace(/\\/g, '/'); + }; + + tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { + + //ignore adding empty strings + if (!chunk) { + return; + } + + var lines, + sourceLines, + columns, + sourceColumns, + i; + + if (fileInfo) { + var inputSource = this._contentsMap[fileInfo.filename].substring(0, index); + sourceLines = inputSource.split("\n"); + sourceColumns = sourceLines[sourceLines.length-1]; + } + + lines = chunk.split("\n"); + columns = lines[lines.length-1]; + + if (fileInfo) { + if (!mapLines) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column}, + original: { line: sourceLines.length, column: sourceColumns.length}, + source: this.normalizeFilename(fileInfo.filename)}); + } else { + for(i = 0; i < lines.length; i++) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0}, + original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0}, + source: this.normalizeFilename(fileInfo.filename)}); + } + } + } + + if (lines.length === 1) { + this._column += columns.length; + } else { + this._lineNumber += lines.length - 1; + this._column = columns.length; + } + + this._css.push(chunk); + }; + + tree.sourceMapOutput.prototype.isEmpty = function() { + return this._css.length === 0; + }; + + tree.sourceMapOutput.prototype.toCSS = function(env) { + this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null }); + + if (this._outputSourceFiles) { + for(var filename in this._contentsMap) { + this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), this._contentsMap[filename]); + } + } + + this._rootNode.genCSS(env, this); + + if (this._css.length > 0) { + var sourceMapFilename, + sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON()); + + if (this._sourceMapFilename) { + sourceMapFilename = this.normalizeFilename(this._sourceMapFilename); + } + + if (this._writeSourceMap) { + this._writeSourceMap(sourceMapContent); + } else { + sourceMapFilename = "data:application/json," + encodeURIComponent(sourceMapContent); + } + + if (sourceMapFilename) { + this._css.push("/*# sourceMappingURL=" + sourceMapFilename + " */"); + } + } + + return this._css.join(''); + }; + +})(require('./tree')); + +// +// browser.js - client-side engine +// +/*global less, window, document, XMLHttpRequest, location */ + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +var logLevel = { + info: 2, + errors: 1, + none: 0 +}; + +// The amount of logging in the javascript console. +// 2 - Information and errors +// 1 - Errors +// 0 - None +// Defaults to 2 +less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : logLevel.info; + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +var typePattern = /^text\/(x-)?less$/; +var cache = null; +var fileCache = {}; + +function log(str, level) { + if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) { + console.log('less: ' + str); + } +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function errorConsole(e, rootHref) { + var template = '{line} {content}'; + var filename = e.filename || rootHref; + var errors = []; + var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + " in " + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + errors.join('\n'); + } else if (e.stack) { + content += e.stack; + } + log(content, logLevel.errors); +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss === null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + if (nextEl) { + nextEl.parentNode.insertBefore(css, nextEl); + } else { + head.appendChild(css); + } + } + if (oldCss && keepOldCss === false) { + oldCss.parentNode.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.', logLevel.info); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save', logLevel.errors); + } + } +} + +function errorHTML(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, errors = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + errors.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +function error(e, rootHref) { + if (!less.errorReporting || less.errorReporting === "html") { + errorHTML(e, rootHref); + } else if (less.errorReporting === "console") { + errorConsole(e, rootHref); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("add", e, rootHref); + } +} + +function removeErrorHTML(path) { + var node = document.getElementById('less-error-message:' + extractId(path)); + if (node) { + node.parentNode.removeChild(node); + } +} + +function removeErrorConsole(path) { + //no action +} + +function removeError(path) { + if (!less.errorReporting || less.errorReporting === "html") { + removeErrorHTML(path); + } else if (less.errorReporting === "console") { + removeErrorConsole(path); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("remove", path); + } +} + +function loadStyles(newVars) { + var styles = document.getElementsByTagName('style'), + style; + for (var i = 0; i < styles.length; i++) { + style = styles[i]; + if (style.type.match(typePattern)) { + var env = new less.tree.parseEnv(less), + lessText = style.innerHTML || ''; + env.filename = document.location.href.replace(/#.*$/, ''); + if (newVars) { + env.useFileCache = true; + lessText += "\n" + newVars; + } + + /*jshint loopfunc:true */ + // use closure to store current value of i + var callback = (function(style) { + return function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }; + })(style); + new(less.Parser)(env).parse(lessText, callback); + } + } +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } else { + try { + /*global ActiveXObject */ + return new ActiveXObject("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX.", logLevel.errors); + return null; + } + } +} + +function doXHR(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + log("XHR: Getting '" + url + "'", logLevel.info); + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } +} + +function loadFile(originalHref, currentFileInfo, callback, env, newVars) { + + if (currentFileInfo && currentFileInfo.currentDirectory && !/^([a-z-]+:)?\//.test(originalHref)) { + originalHref = currentFileInfo.currentDirectory + originalHref; + } + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(originalHref, window.location.href); + var href = hrefParts.url; + var newFileInfo = { + currentDirectory: hrefParts.path, + filename: href + }; + + if (currentFileInfo) { + newFileInfo.entryPath = currentFileInfo.entryPath; + newFileInfo.rootpath = currentFileInfo.rootpath; + newFileInfo.rootFilename = currentFileInfo.rootFilename; + newFileInfo.relativeUrls = currentFileInfo.relativeUrls; + } else { + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + newFileInfo.relativeUrls = env.relativeUrls; + } + + if (newFileInfo.relativeUrls) { + if (env.rootpath) { + newFileInfo.rootpath = extractUrlParts(env.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + if (env.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + if (newVars) { + lessText += "\n" + newVars; + } + callback(null, lessText, href, newFileInfo, { lastModified: new Date() }); + } catch (e) { + callback(e, null, href); + } + return; + } + + doXHR(href, env.mime, function (data, lastModified) { + // per file cache + fileCache[href] = data; + + // Use remote copy (re-parse) + try { + callback(null, data, href, newFileInfo, { lastModified: lastModified }); + } catch (e) { + callback(e, null, href); + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href); + }); +} + +function loadStyleSheet(sheet, callback, reload, remaining, newVars) { + + var env = new less.tree.parseEnv(less); + env.mime = sheet.type; + + if (newVars) { + env.useFileCache = true; + } + + loadFile(sheet.href, null, function(e, data, path, newFileInfo, webInfo) { + + if (webInfo) { + webInfo.remaining = remaining; + + var css = cache && cache.getItem(path), + timestamp = cache && cache.getItem(path + ':timestamp'); + + if (!reload && timestamp && webInfo.lastModified && + (new(Date)(webInfo.lastModified).valueOf() === + new(Date)(timestamp).valueOf())) { + // Use local copy + createCSS(css, sheet); + webInfo.local = true; + callback(null, null, data, sheet, webInfo, path); + return; + } + } + + //TODO add tests around how this behaves when reloading + removeError(path); + + if (data) { + env.currentFileInfo = newFileInfo; + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, webInfo, path); + } catch (e) { + callback(e, null, null, sheet); + } + }); + } else { + callback(e, null, null, sheet, webInfo, path); + } + }, env, newVars); +} + +function loadStyleSheets(callback, reload, newVars) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), newVars); + } +} + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true; +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +less.modifyVars = function(record) { + var newVars = ""; + for (var name in record) { + newVars += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + less.refresh(false, newVars); +}; + +less.refresh = function (reload, newVars) { + var startTime, endTime; + startTime = endTime = new Date(); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache.", logLevel.info); + } else { + log("parsed " + sheet.href + " successfully.", logLevel.info); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info); + if (env.remaining === 0) { + log("css generated in " + (new Date() - startTime) + 'ms', logLevel.info); + } + endTime = new Date(); + }, reload, newVars); + + loadStyles(newVars); +}; + +less.refreshStyles = loadStyles; + +less.Parser.fileLoader = loadFile; + +less.refresh(less.env === 'development'); + +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} + +})(window); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.0.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.0.min.js new file mode 100644 index 000000000..73c03b64c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.0.min.js @@ -0,0 +1,13 @@ +/*! + * LESS - Leaner CSS v1.5.0 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache v2 License. + * + * @licence + */ + +function require(a){return window.less[a.split("/")[1]]}function log(a,b){"development"==less.env&&"undefined"!=typeof console&&less.logLevel>=b&&console.log("less: "+a)}function extractId(a){return a.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function errorConsole(a,b){var c="{line} {content}",d=a.filename||b,e=[],f=(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+" in "+d+" ",g=function(a,b,d){void 0!==a.extract[b]&&e.push(c.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,d).replace(/\{content\}/,a.extract[b]))};a.extract?(g(a,0,""),g(a,1,"line"),g(a,2,""),f+="on line "+a.line+", column "+(a.column+1)+":\n"+e.join("\n")):a.stack&&(f+=a.stack),log(f,logLevel.errors)}function createCSS(a,b,c){var d=b.href||"",e="less:"+(b.title||extractId(d)),f=document.getElementById(e),g=!1,h=document.createElement("style");if(h.setAttribute("type","text/css"),b.media&&h.setAttribute("media",b.media),h.id=e,h.styleSheet)try{h.styleSheet.cssText=a}catch(i){throw new Error("Couldn't reassign styleSheet.cssText.")}else h.appendChild(document.createTextNode(a)),g=null!==f&&f.childNodes.length>0&&h.childNodes.length>0&&f.firstChild.nodeValue===h.firstChild.nodeValue;var j=document.getElementsByTagName("head")[0];if(null===f||g===!1){var k=b&&b.nextSibling||null;k?k.parentNode.insertBefore(h,k):j.appendChild(h)}if(f&&g===!1&&f.parentNode.removeChild(f),c&&cache){log("saving "+d+" to cache.",logLevel.info);try{cache.setItem(d,a),cache.setItem(d+":timestamp",c)}catch(i){log("failed to save",logLevel.errors)}}}function errorHTML(a,b){var c,d,e="less-error-message:"+extractId(b||""),f='
  • {content}
  • ',g=document.createElement("div"),h=[],i=a.filename||b,j=i.match(/([^\/]+(\?.*)?)$/)[1];g.id=e,g.className="less-error-message",d="

    "+(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){void 0!==a.extract[b]&&h.push(f.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.extract?(k(a,0,""),k(a,1,"line"),k(a,2,""),d+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+h.join("")+"
    "):a.stack&&(d+="
    "+a.stack.split("\n").slice(1).join("
    ")),g.innerHTML=d,createCSS([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),g.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),"development"==less.env&&(c=setInterval(function(){document.body&&(document.getElementById(e)?document.body.replaceChild(g,document.getElementById(e)):document.body.insertBefore(g,document.body.firstChild),clearInterval(c))},10))}function error(a,b){less.errorReporting&&"html"!==less.errorReporting?"console"===less.errorReporting?errorConsole(a,b):"function"==typeof less.errorReporting&&less.errorReporting("add",a,b):errorHTML(a,b)}function removeErrorHTML(a){var b=document.getElementById("less-error-message:"+extractId(a));b&&b.parentNode.removeChild(b)}function removeErrorConsole(){}function removeError(a){less.errorReporting&&"html"!==less.errorReporting?"console"===less.errorReporting?removeErrorConsole(a):"function"==typeof less.errorReporting&&less.errorReporting("remove",a):removeErrorHTML(a)}function loadStyles(a){for(var b,c=document.getElementsByTagName("style"),d=0;d0&&(h.splice(c-1,2),c-=2)}return g.hostPart=f[1],g.directories=h,g.path=f[1]+h.join("/"),g.fileUrl=g.path+(f[4]||""),g.url=g.fileUrl+(f[5]||""),g}function pathDiff(a,b){var c,d,e,f,g=extractUrlParts(a),h=extractUrlParts(b),i="";if(g.hostPart!==h.hostPart)return"";for(d=Math.max(h.directories.length,g.directories.length),c=0;d>c&&h.directories[c]===g.directories[c];c++);for(f=h.directories.slice(c),e=g.directories.slice(c),c=0;c=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):"function"==typeof d&&d(b.status,a)}var f=getXMLHttpRequest(),g=isFileProtocol?less.fileAsync:less.async;"function"==typeof f.overrideMimeType&&f.overrideMimeType("text/css"),log("XHR: Getting '"+a+"'",logLevel.info),f.open("GET",a,g),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),isFileProtocol&&!less.fileAsync?0===f.status||f.status>=200&&f.status<300?c(f.responseText):d(f.status,a):g?f.onreadystatechange=function(){4==f.readyState&&e(f,c,d)}:e(f,c,d)}function loadFile(a,b,c,d,e){b&&b.currentDirectory&&!/^([a-z-]+:)?\//.test(a)&&(a=b.currentDirectory+a);var f=extractUrlParts(a,window.location.href),g=f.url,h={currentDirectory:f.path,filename:g};if(b?(h.entryPath=b.entryPath,h.rootpath=b.rootpath,h.rootFilename=b.rootFilename,h.relativeUrls=b.relativeUrls):(h.entryPath=f.path,h.rootpath=less.rootpath||f.path,h.rootFilename=g,h.relativeUrls=d.relativeUrls),h.relativeUrls&&(h.rootpath=d.rootpath?extractUrlParts(d.rootpath+pathDiff(f.path,h.entryPath)).path:f.path),d.useFileCache&&fileCache[g])try{var i=fileCache[g];e&&(i+="\n"+e),c(null,i,g,h,{lastModified:new Date})}catch(j){c(j,null,g)}else doXHR(g,d.mime,function(a,b){fileCache[g]=a;try{c(null,a,g,h,{lastModified:b})}catch(d){c(d,null,g)}},function(a,b){c({type:"File",message:"'"+b+"' wasn't found ("+a+")"},null,g)})}function loadStyleSheet(a,b,c,d,e){var f=new less.tree.parseEnv(less);f.mime=a.type,e&&(f.useFileCache=!0),loadFile(a.href,null,function(e,g,h,i,j){if(j){j.remaining=d;var k=cache&&cache.getItem(h),l=cache&&cache.getItem(h+":timestamp");if(!c&&l&&j.lastModified&&new Date(j.lastModified).valueOf()===new Date(l).valueOf())return createCSS(k,a),j.local=!0,b(null,null,g,a,j,h),void 0}removeError(h),g?(f.currentFileInfo=i,new less.Parser(f).parse(g,function(c,d){if(c)return b(c,null,null,a);try{b(c,d,g,a,j,h)}catch(c){b(c,null,null,a)}})):b(e,null,null,a,j,h)},f,e)}function loadStyleSheets(a,b,c){for(var d=0;dv&&(u[q]=u[q].slice(p-v),v=p)}function e(a){var b=a.charCodeAt(0);return 32===b||10===b||9===b}function f(a){var b,c;if(a instanceof Function)return a.call(w.parsers);if("string"==typeof a)b=o.charAt(p)===a?a:null,c=1,d();else{if(d(),!(b=a.exec(u[q])))return null;c=b[0].length}return b?(g(c),"string"==typeof b?b:1===b.length?b[0]:b):void 0}function g(a){for(var b=p,c=q,d=p+u[q].length,f=p+=a;d>p&&e(o.charAt(p));)p++;return u[q]=u[q].slice(a+(p-f)),v=p,0===u[q].length&&q=0&&"\n"!==b.charAt(c);)e++;return"number"==typeof a&&(d=(b.slice(0,a).match(/\n/g)||"").length),{line:d,column:e}}function m(a,b,c){var d=c.currentFileInfo.filename;return"browser"!==less.mode&&"rhino"!==less.mode&&(d=require("path").resolve(d)),{lineNumber:l(a,b).line+1,fileName:d}}function n(a,b){var c=k(a,b),d=l(a.index,c),e=d.line,f=d.column,g=a.call&&l(a.call,c).line,h=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.currentFileInfo.filename,this.index=a.index,this.line="number"==typeof e?e+1:null,this.callLine=g+1,this.callExtract=h[g],this.stack=a.stack,this.column=f,this.extract=[h[e-1],h[e],h[e+1]]}var o,p,q,r,s,t,u,v,w,x=a&&a.filename;a instanceof tree.parseEnv||(a=new tree.parseEnv(a));var y=this.imports={paths:a.paths||[],queue:[],files:a.files,contents:a.contents,mime:a.mime,error:null,push:function(b,c,d,e){var f=this;this.queue.push(b);var g=function(a,c,d){f.queue.splice(f.queue.indexOf(b),1);var g=d in f.files||d===x;f.files[d]=c,a&&!f.error&&(f.error=a),e(a,c,g,d)};less.Parser.importer?less.Parser.importer(b,c,g,a):less.Parser.fileLoader(b,c,function(b,e,f,h){if(b)return g(b),void 0;var i=new tree.parseEnv(a);i.currentFileInfo=h,i.processImports=!1,i.contents[f]=e,(c.reference||d.reference)&&(h.reference=!0),d.inline?g(null,e,f):new less.Parser(i).parse(e,function(a,b){g(a,b,f)})},a)}};return n.prototype=new Error,n.prototype.constructor=n,this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,w={imports:y,parse:function(b,c){var d,e,g,h=null;if(p=q=v=t=0,o=b.replace(/\r\n/g,"\n"),o=o.replace(/^\uFEFF/,""),w.imports.contents[a.currentFileInfo.filename]=o,u=function(b){for(var c,d,e,f,g=0,i=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,j=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,k=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,l=0,m=b[0],p=0;p0?"missing closing `}`":"missing opening `{`",filename:a.currentFileInfo.filename},a)),b.map(function(a){return a.join("")})}([[]]),h)return c(new n(h,a));try{d=new tree.Ruleset([],f(this.parsers.primary)),d.root=!0,d.firstRoot=!0}catch(i){return c(new n(i,a))}if(d.toCSS=function(b){return function(c,d){c=c||{};var e,f,g=new tree.evalEnv(c);"object"!=typeof d||Array.isArray(d)||(d=Object.keys(d).map(function(a){var b=d[a];return b instanceof tree.Value||(b instanceof tree.Expression||(b=new tree.Expression([b])),b=new tree.Value([b])),new tree.Rule("@"+a,b,!1,null,0)}),g.frames=[new tree.Ruleset(null,d)]);try{e=b.call(this,g),(new tree.joinSelectorVisitor).run(e),(new tree.processExtendsVisitor).run(e),new tree.toCSSVisitor({compress:Boolean(c.compress)}).run(e),c.sourceMap&&(e=new tree.sourceMapOutput({writeSourceMap:c.writeSourceMap,rootNode:e,contentsMap:w.imports.contents,sourceMapFilename:c.sourceMapFilename,outputFilename:c.sourceMapOutputFilename,sourceMapBasepath:c.sourceMapBasepath,sourceMapRootpath:c.sourceMapRootpath,outputSourceFiles:c.outputSourceFiles,sourceMapGenerator:c.sourceMapGenerator})),f=e.toCSS({compress:Boolean(c.compress),dumpLineNumbers:a.dumpLineNumbers,strictUnits:Boolean(c.strictUnits)})}catch(h){throw new n(h,a)}return c.cleancss&&"node"===less.mode?require("clean-css").process(f):c.compress?f.replace(/(^(\s)+)|((\s)+$)/g,""):f}}(d.eval),p57||43>b||47===b||44==b))return(a=f(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))?new tree.Dimension(a[1],a[2]):void 0},unicodeDescriptor:function(){var a;return(a=f(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))?new tree.UnicodeDescriptor(a[0]):void 0},javascript:function(){var b,c,d=p;return"~"===o.charAt(d)&&(d++,c=!0),"`"===o.charAt(d)?(void 0===a.javascriptEnabled||a.javascriptEnabled||i("You are using JavaScript, which has been disabled."),c&&f("~"),(b=f(/^`([^`]*)`/))?new tree.JavaScript(b[1],p,c):void 0):void 0}},variable:function(){var a;return"@"===o.charAt(p)&&(a=f(/^(@[\w-]+)\s*:/))?a[1]:void 0},extend:function(a){var b,c,d,e=p,g=[];if(f(a?/^&:extend\(/:/^:extend\(/)){do{for(d=null,b=[];;){if(d=f(/^(all)(?=\s*(\)|,))/))break;if(c=f(this.element),!c)break;b.push(c)}d=d&&d[1],g.push(new tree.Extend(new tree.Selector(b),d,e))}while(f(","));return h(/^\)/),a&&h(/^;/),g}},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var d,e,g,i=[],k=p,l=o.charAt(p),m=!1;if("."===l||"#"===l){for(b();d=f(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/);)i.push(new tree.Element(e,d,p,a.currentFileInfo)),e=f(">");return f("(")&&(g=this.mixin.args.call(this,!0).args,h(")")),g=g||[],f(this.important)&&(m=!0),i.length>0&&(f(";")||j("}"))?new tree.mixin.Call(i,g,k,a.currentFileInfo,m):(c(),void 0)}},args:function(a){for(var b,c,d,e,g,j,k=[],l=[],m=[],n={args:null,variadic:!1};;){if(a)j=f(this.expression);else{if(f(this.comments),"."===o.charAt(p)&&f(/^\.{3}/)){n.variadic=!0,f(";")&&!b&&(b=!0),(b?l:m).push({variadic:!0});break}j=f(this.entities.variable)||f(this.entities.literal)||f(this.entities.keyword)}if(!j)break;e=null,j.throwAwayComments&&j.throwAwayComments(),g=j;var q=null;if(a?1==j.value.length&&(q=j.value[0]):q=j,q&&q instanceof tree.Variable)if(f(":"))k.length>0&&(b&&i("Cannot mix ; and , as delimiter types"),c=!0),g=h(this.expression),e=d=q.name;else{if(!a&&f(/^\.{3}/)){n.variadic=!0,f(";")&&!b&&(b=!0),(b?l:m).push({name:j.name,variadic:!0});break}a||(d=e=q.name,g=null)}g&&k.push(g),m.push({name:e,value:g}),f(",")||(f(";")||b)&&(c&&i("Cannot mix ; and , as delimiter types"),b=!0,k.length>1&&(g=new tree.Value(k)),l.push({name:d,value:g}),d=null,k=[],c=!1)}return n.args=b?l:m,n},definition:function(){var a,d,e,g,i=[],k=!1;if(!("."!==o.charAt(p)&&"#"!==o.charAt(p)||j(/^[^{]*\}/))&&(b(),d=f(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/))){a=d[1];var l=this.mixin.args.call(this,!1);if(i=l.args,k=l.variadic,f(")")||(t=p,c()),f(this.comments),f(/^when/)&&(g=h(this.conditions,"expected condition")),e=f(this.block))return new tree.mixin.Definition(a,i,e,g,k);c()}}},entity:function(){return f(this.entities.literal)||f(this.entities.variable)||f(this.entities.url)||f(this.entities.call)||f(this.entities.keyword)||f(this.entities.javascript)||f(this.comment)},end:function(){return f(";")||j("}")},alpha:function(){var a;if(f(/^\(opacity=/i))return(a=f(/^\d+/)||f(this.entities.variable))?(h(")"),new tree.Alpha(a)):void 0},element:function(){var b,c,d;return c=f(this.combinator),b=f(/^(?:\d+\.\d+|\d+)%/)||f(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||f("*")||f("&")||f(this.attribute)||f(/^\([^()@]+\)/)||f(/^[\.#](?=@)/)||f(this.entities.variableCurly),b||f("(")&&(d=f(this.selector))&&f(")")&&(b=new tree.Paren(d)),b?new tree.Element(c,b,p,a.currentFileInfo):void 0},combinator:function(){var a=o.charAt(p);if(">"===a||"+"===a||"~"===a||"|"===a){for(p++;o.charAt(p).match(/\s/);)p++;return new tree.Combinator(a)}return o.charAt(p-1).match(/\s/)?new tree.Combinator(" "):new tree.Combinator(null)},lessSelector:function(){return this.selector(!0)},selector:function(b){for(var c,d,e,g,j,k=[],l=[];(b&&(e=f(this.extend))||b&&(g=f(/^when/))||(c=f(this.element)))&&(g?j=h(this.conditions,"expected condition"):j?i("CSS guard can only be used at the end of selector"):e?l.push.apply(l,e):(l.length&&i("Extend can only be used at the end of selector"),d=o.charAt(p),k.push(c),c=null),"{"!==d&&"}"!==d&&";"!==d&&","!==d&&")"!==d););return k.length>0?new tree.Selector(k,l,j,p,a.currentFileInfo):(l.length&&i("Extend must be used to extend a selector, it cannot be used on its own"),void 0)},attribute:function(){var a,b,c;if(f("["))return(a=f(this.entities.variableCurly))||(a=h(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/)),(c=f(/^[|~*$^]?=/))&&(b=f(this.entities.quoted)||f(/^[0-9]+%/)||f(/^[\w-]+/)||f(this.entities.variableCurly)),h("]"),new tree.Attribute(a,c,b)},block:function(){var a;return f("{")&&(a=f(this.primary))&&f("}")?a:void 0},ruleset:function(){var d,e,g,h=[];for(b(),a.dumpLineNumbers&&(g=m(p,o,a));(d=f(this.lessSelector))&&(h.push(d),f(this.comments),f(","));)d.condition&&i("Guards are only currently allowed on a single selector."),f(this.comments);if(h.length>0&&(e=f(this.block))){var j=new tree.Ruleset(h,e,a.strictImports);return a.dumpLineNumbers&&(j.debugInfo=g),j}t=p,c()},rule:function(d){var e,g,h,i=o.charAt(p),j=!1;if(b(),"."!==i&&"#"!==i&&"&"!==i&&(e=f(this.variable)||f(this.ruleProperty))){if(g=d||!a.compress&&"@"!==e.charAt(0)?f(this.anonymousValue)||f(this.value):f(this.value)||f(this.anonymousValue),h=f(this.important),"+"===e[e.length-1]&&(j=!0,e=e.substr(0,e.length-1)),g&&f(this.end))return new tree.Rule(e,g,h,j,s,a.currentFileInfo);if(t=p,c(),g&&!d)return this.rule(!0)}},anonymousValue:function(){var a;return(a=/^([^@+\/'"*`(;{}-]*);/.exec(u[q]))?(p+=a[0].length-1,new tree.Anonymous(a[1])):void 0},"import":function(){var d,e,g=p;b();var h=f(/^@import?\s+/),i=(h?f(this.importOptions):null)||{};return h&&(d=f(this.entities.quoted)||f(this.entities.url))&&(e=f(this.mediaFeatures),f(";"))?(e=e&&new tree.Value(e),new tree.Import(d,e,i,g,a.currentFileInfo)):(c(),void 0)},importOptions:function(){var a,b,c,d={};if(!f("("))return null;do if(a=f(this.importOption)){switch(b=a,c=!0,b){case"css":b="less",c=!1;break;case"once":b="multiple",c=!1}if(d[b]=c,!f(","))break}while(a);return h(")"),d},importOption:function(){var a=f(/^(less|css|multiple|once|inline|reference)/);return a?a[1]:void 0},mediaFeature:function(){var b,c,d=[];do if(b=f(this.entities.keyword)||f(this.entities.variable))d.push(b);else if(f("(")){if(c=f(this.property),b=f(this.value),!f(")"))return null;if(c&&b)d.push(new tree.Paren(new tree.Rule(c,b,null,null,p,a.currentFileInfo,!0)));else{if(!b)return null;d.push(new tree.Paren(b))}}while(b);return d.length>0?new tree.Expression(d):void 0},mediaFeatures:function(){var a,b=[];do if(a=f(this.mediaFeature)){if(b.push(a),!f(","))break}else if((a=f(this.entities.variable))&&(b.push(a),!f(",")))break;while(a);return b.length>0?b:null},media:function(){var b,c,d,e;return a.dumpLineNumbers&&(e=m(p,o,a)),f(/^@media/)&&(b=f(this.mediaFeatures),c=f(this.block))?(d=new tree.Media(c,b,p,a.currentFileInfo),a.dumpLineNumbers&&(d.debugInfo=e),d):void 0},directive:function(){var d,e,g,h,i,j,k,l;if("@"===o.charAt(p)){if(e=f(this["import"])||f(this.media))return e;if(b(),d=f(/^@[a-z-]+/)){switch(h=d,"-"==d.charAt(1)&&d.indexOf("-",2)>0&&(h="@"+d.slice(d.indexOf("-",2)+1)),h){case"@font-face":i=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":i=!0;break;case"@host":case"@page":case"@document":case"@supports":case"@keyframes":i=!0,j=!0;break;case"@namespace":k=!0}if(j&&(l=(f(/^[^{]+/)||"").trim(),l&&(d+=" "+l)),i){if(g=f(this.block))return new tree.Directive(d,g,p,a.currentFileInfo)}else if((e=k?f(this.expression):f(this.entity))&&f(";")){var n=new tree.Directive(d,e,p,a.currentFileInfo);return a.dumpLineNumbers&&(n.debugInfo=m(p,o,a)),n}c()}}},value:function(){for(var a,b=[];(a=f(this.expression))&&(b.push(a),f(",")););return b.length>0?new tree.Value(b):void 0},important:function(){return"!"===o.charAt(p)?f(/^! *important/):void 0},sub:function(){var a,b;return f("(")&&(a=f(this.addition))?(b=new tree.Expression([a]),h(")"),b.parens=!0,b):void 0},multiplication:function(){var a,b,c,d,g;if(a=f(this.operand)){for(g=e(o.charAt(p-1));!j(/^\/[*\/]/)&&(c=f("/")||f("*"))&&(b=f(this.operand));)a.parensInOp=!0,b.parensInOp=!0,d=new tree.Operation(c,[d||a,b],g),g=e(o.charAt(p-1));return d||a}},addition:function(){var a,b,c,d,g;if(a=f(this.multiplication)){for(g=e(o.charAt(p-1));(c=f(/^[-+]\s+/)||!g&&(f("+")||f("-")))&&(b=f(this.multiplication));)a.parensInOp=!0,b.parensInOp=!0,d=new tree.Operation(c,[d||a,b],g),g=e(o.charAt(p-1));return d||a}},conditions:function(){var a,b,c,d=p;if(a=f(this.condition)){for(;j(/^,\s*(not\s*)?\(/)&&f(",")&&(b=f(this.condition));)c=new tree.Condition("or",c||a,b,d);return c||a}},condition:function(){var a,b,c,d,e=p,g=!1;return f(/^not/)&&(g=!0),h("("),(a=f(this.addition)||f(this.entities.keyword)||f(this.entities.quoted))?((d=f(/^(?:>=|<=|=<|[<=>])/))?(b=f(this.addition)||f(this.entities.keyword)||f(this.entities.quoted))?c=new tree.Condition(d,a,b,e,g):i("expected expression"):c=new tree.Condition("=",a,new tree.Keyword("true"),e,g),h(")"),f(/^and/)?new tree.Condition("and",c,f(this.condition)):c):void 0},operand:function(){var a,b=o.charAt(p+1);"-"!==o.charAt(p)||"@"!==b&&"("!==b||(a=f("-"));var c=f(this.sub)||f(this.entities.dimension)||f(this.entities.color)||f(this.entities.variable)||f(this.entities.call);return a&&(c.parensInOp=!0,c=new tree.Negative(c)),c},expression:function(){for(var a,b,c=[];a=f(this.addition)||f(this.entity);)c.push(a),!j(/^\/[\/*]/)&&(b=f("/"))&&c.push(new tree.Anonymous(b));return c.length>0?new tree.Expression(c):void 0},property:function(){var a;return(a=f(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/))?a[1]:void 0},ruleProperty:function(){var a;return(a=f(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/))?a[1]+(a[2]||""):void 0}}}},function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b,c){return b instanceof a.Dimension&&b.unit.is("%")?parseFloat(b.value*c/100):d(b)}function d(b){if(b instanceof a.Dimension)return parseFloat(b.unit.is("%")?b.value/100:b.value);if("number"==typeof b)return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function e(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,e,f,g){var h=[b,e,f].map(function(a){return c(a,256)});return g=d(g),new a.Color(h,g)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,c,f){function g(a){return a=0>a?a+1:a>1?a-1:a,1>6*a?i+6*(h-i)*a:1>2*a?h:2>3*a?i+6*(h-i)*(2/3-a):i}a=d(a)%360/360,b=e(d(b)),c=e(d(c)),f=e(d(f));var h=.5>=c?c*(b+1):c+b-c*b,i=2*c-h;return this.rgba(255*g(a+1/3),255*g(a),255*g(a-1/3),f)},hsv:function(a,b,c){return this.hsva(a,b,c,1)},hsva:function(a,b,c,e){a=360*(d(a)%360/360),b=d(b),c=d(c),e=d(e);var f,g;f=Math.floor(a/60%6),g=a/60-f;var h=[c,c*(1-b),c*(1-g*b),c*(1-(1-g)*b)],i=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(255*h[i[f][0]],255*h[i[f][1]],255*h[i[f][2]],e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(100*b.toHSL().s),"%")},lightness:function(b){return new a.Dimension(Math.round(100*b.toHSL().l),"%")},hsvhue:function(b){return new a.Dimension(Math.round(b.toHSV().h))},hsvsaturation:function(b){return new a.Dimension(Math.round(100*b.toHSV().s),"%")},hsvvalue:function(b){return new a.Dimension(Math.round(100*b.toHSV().v),"%")},red:function(b){return new a.Dimension(b.rgb[0])},green:function(b){return new a.Dimension(b.rgb[1])},blue:function(b){return new a.Dimension(b.rgb[2])},alpha:function(b){return new a.Dimension(b.toHSL().a)},luma:function(b){return new a.Dimension(Math.round(100*b.luma()*b.alpha),"%")},saturate:function(a,c){if(!a.rgb)return null;var d=a.toHSL();return d.s+=c.value/100,d.s=e(d.s),b(d)},desaturate:function(a,c){var d=a.toHSL();return d.s-=c.value/100,d.s=e(d.s),b(d)},lighten:function(a,c){var d=a.toHSL();return d.l+=c.value/100,d.l=e(d.l),b(d)},darken:function(a,c){var d=a.toHSL();return d.l-=c.value/100,d.l=e(d.l),b(d)},fadein:function(a,c){var d=a.toHSL();return d.a+=c.value/100,d.a=e(d.a),b(d)},fadeout:function(a,c){var d=a.toHSL();return d.a-=c.value/100,d.a=e(d.a),b(d)},fade:function(a,c){var d=a.toHSL();return d.a=c.value/100,d.a=e(d.a),b(d)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=0>e?360+e:e,b(d)},mix:function(b,c,d){d||(d=new a.Dimension(50));var e=d.value/100,f=2*e-1,g=b.toHSL().a-c.toHSL().a,h=((-1==f*g?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},contrast:function(a,b,c,e){if(!a.rgb)return null;if("undefined"==typeof c&&(c=this.rgba(255,255,255,1)),"undefined"==typeof b&&(b=this.rgba(0,0,0,1)),b.luma()>c.luma()){var f=c;c=b,b=f}return e="undefined"==typeof e?.43:d(e),a.luma()*a.alphah.value)&&(j[e]=f)):(k[i]=j.length,j.push(f))):j.push(f);return 1==j.length?j[0]:(c=j.map(function(a){return a.toCSS(this.env)}).join(this.env.compress?",":", "),new a.Anonymous((b?"min":"max")+"("+c+")"))},min:function(){return this._minmax(!0,arguments)},max:function(){return this._minmax(!1,arguments)},argb:function(b){return new a.Anonymous(b.toARGB())},percentage:function(b){return new a.Dimension(100*b.value,"%")},color:function(b){if(b instanceof a.Quoted){var c,d=b.value;if(c=a.Color.fromKeyword(d))return c;if(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(d))return new a.Color(d.slice(1));throw{type:"Argument",message:"argument must be a color keyword or 3/6 digit hex e.g. #FFF"}}throw{type:"Argument",message:"argument must be a string"}},iscolor:function(b){return this._isa(b,a.Color)},isnumber:function(b){return this._isa(b,a.Dimension)},isstring:function(b){return this._isa(b,a.Quoted)},iskeyword:function(b){return this._isa(b,a.Keyword)},isurl:function(b){return this._isa(b,a.URL) +},ispixel:function(a){return this.isunit(a,"px")},ispercentage:function(a){return this.isunit(a,"%")},isem:function(a){return this.isunit(a,"em")},isunit:function(b,c){return b instanceof a.Dimension&&b.unit.is(c.value||c)?a.True:a.False},_isa:function(b,c){return b instanceof c?a.True:a.False},multiply:function(a,b){var c=a.rgb[0]*b.rgb[0]/255,d=a.rgb[1]*b.rgb[1]/255,e=a.rgb[2]*b.rgb[2]/255;return this.rgb(c,d,e)},screen:function(a,b){var c=255-(255-a.rgb[0])*(255-b.rgb[0])/255,d=255-(255-a.rgb[1])*(255-b.rgb[1])/255,e=255-(255-a.rgb[2])*(255-b.rgb[2])/255;return this.rgb(c,d,e)},overlay:function(a,b){var c=a.rgb[0]<128?2*a.rgb[0]*b.rgb[0]/255:255-2*(255-a.rgb[0])*(255-b.rgb[0])/255,d=a.rgb[1]<128?2*a.rgb[1]*b.rgb[1]/255:255-2*(255-a.rgb[1])*(255-b.rgb[1])/255,e=a.rgb[2]<128?2*a.rgb[2]*b.rgb[2]/255:255-2*(255-a.rgb[2])*(255-b.rgb[2])/255;return this.rgb(c,d,e)},softlight:function(a,b){var c=b.rgb[0]*a.rgb[0]/255,d=c+a.rgb[0]*(255-(255-a.rgb[0])*(255-b.rgb[0])/255-c)/255;c=b.rgb[1]*a.rgb[1]/255;var e=c+a.rgb[1]*(255-(255-a.rgb[1])*(255-b.rgb[1])/255-c)/255;c=b.rgb[2]*a.rgb[2]/255;var f=c+a.rgb[2]*(255-(255-a.rgb[2])*(255-b.rgb[2])/255-c)/255;return this.rgb(d,e,f)},hardlight:function(a,b){var c=b.rgb[0]<128?2*b.rgb[0]*a.rgb[0]/255:255-2*(255-b.rgb[0])*(255-a.rgb[0])/255,d=b.rgb[1]<128?2*b.rgb[1]*a.rgb[1]/255:255-2*(255-b.rgb[1])*(255-a.rgb[1])/255,e=b.rgb[2]<128?2*b.rgb[2]*a.rgb[2]/255:255-2*(255-b.rgb[2])*(255-a.rgb[2])/255;return this.rgb(c,d,e)},difference:function(a,b){var c=Math.abs(a.rgb[0]-b.rgb[0]),d=Math.abs(a.rgb[1]-b.rgb[1]),e=Math.abs(a.rgb[2]-b.rgb[2]);return this.rgb(c,d,e)},exclusion:function(a,b){var c=a.rgb[0]+b.rgb[0]*(255-a.rgb[0]-a.rgb[0])/255,d=a.rgb[1]+b.rgb[1]*(255-a.rgb[1]-a.rgb[1])/255,e=a.rgb[2]+b.rgb[2]*(255-a.rgb[2]-a.rgb[2])/255;return this.rgb(c,d,e)},average:function(a,b){var c=(a.rgb[0]+b.rgb[0])/2,d=(a.rgb[1]+b.rgb[1])/2,e=(a.rgb[2]+b.rgb[2])/2;return this.rgb(c,d,e)},negation:function(a,b){var c=255-Math.abs(255-b.rgb[0]-a.rgb[0]),d=255-Math.abs(255-b.rgb[1]-a.rgb[1]),e=255-Math.abs(255-b.rgb[2]-a.rgb[2]);return this.rgb(c,d,e)},tint:function(a,b){return this.mix(this.rgb(255,255,255),a,b)},shade:function(a,b){return this.mix(this.rgb(0,0,0),a,b)},extract:function(a,b){return b=b.value-1,Array.isArray(a.value)?a.value[b]:Array(a)[b]},length:function(b){var c=Array.isArray(b.value)?b.value.length:1;return new a.Dimension(c)},"data-uri":function(b,c){if("undefined"!=typeof window)return new a.URL(c||b,this.currentFileInfo).eval(this.env);var d=b.value,e=c&&c.value,f=require("fs"),g=require("path"),h=!1;if(arguments.length<2&&(e=d),this.env.isPathRelative(e)&&(e=this.currentFileInfo.relativeUrls?g.join(this.currentFileInfo.currentDirectory,e):g.join(this.currentFileInfo.entryPath,e)),arguments.length<2){var i;try{i=require("mime")}catch(j){i=a._mime}d=i.lookup(e);var k=i.charsets.lookup(d);h=["US-ASCII","UTF-8"].indexOf(k)<0,h&&(d+=";base64")}else h=/;base64$/.test(d);var l=f.readFileSync(e),m=32,n=parseInt(l.length/1024,10);if(n>=m&&this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",e,n,m),new a.URL(c||b,this.currentFileInfo).eval(this.env);l=h?l.toString("base64"):encodeURIComponent(l);var o="'data:"+d+","+l+"'";return new a.URL(new a.Anonymous(o))},"svg-gradient":function(b){function c(){throw{type:"Argument",message:"svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]"}}arguments.length<3&&c();var d,e,f,g,h,i,j,k=Array.prototype.slice.call(arguments,1),l="linear",m='x="0" y="0" width="1" height="1"',n=!0,o={compress:!1},p=b.toCSS(o);switch(p){case"to bottom":d='x1="0%" y1="0%" x2="0%" y2="100%"';break;case"to right":d='x1="0%" y1="0%" x2="100%" y2="0%"';break;case"to bottom right":d='x1="0%" y1="0%" x2="100%" y2="100%"';break;case"to top right":d='x1="0%" y1="100%" x2="100%" y2="0%"';break;case"ellipse":case"ellipse at center":l="radial",d='cx="50%" cy="50%" r="75%"',m='x="-50" y="-50" width="101" height="101"';break;default:throw{type:"Argument",message:"svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'"}}for(e='<'+l+'Gradient id="gradient" gradientUnits="userSpaceOnUse" '+d+">",f=0;fj?' stop-opacity="'+j+'"':"")+"/>";if(e+=""+"',n)try{e=new Buffer(e).toString("base64")}catch(q){n=!1}return e="'data:image/svg+xml"+(n?";base64":"")+","+e+"'",new a.URL(new a.Anonymous(e))}},a._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(b){var c=require("path").extname(b),d=a._mime._types[c];if(void 0===d)throw new Error('Optional dependency "mime" is required for '+c);return d},charsets:{lookup:function(a){return a&&/^text\//.test(a)?"UTF-8":""}}};for(var f=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],g=function(a,b){return function(c){return null!=b&&(c=c.unify()),this._math(Math[a],b,c)}},h=0;h1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)},a.toCSS=function(a){var b=[];return this.genCSS(a,{add:function(a){b.push(a)},isEmpty:function(){return 0===b.length}}),b.join("")},a.outputRuleset=function(a,b,c){b.add(a.compress?"{":" {\n"),a.tabLevel=(a.tabLevel||0)+1;for(var d=a.compress?"":Array(a.tabLevel+1).join(" "),e=a.compress?"":Array(a.tabLevel).join(" "),f=0;fb?-1:1},genCSS:function(a,b){b.add(this.value,this.currentFileInfo,this.index,this.mapLines)},toCSS:a.toCSS}}(require("../tree")),function(a){a.Assignment=function(a,b){this.key=a,this.value=b},a.Assignment.prototype={type:"Assignment",accept:function(a){this.value=a.visit(this.value)},eval:function(b){return this.value.eval?new a.Assignment(this.key,this.value.eval(b)):this},genCSS:function(a,b){b.add(this.key+"="),this.value.genCSS?this.value.genCSS(a,b):b.add(this.value)},toCSS:a.toCSS}}(require("../tree")),function(a){a.Call=function(a,b,c,d){this.name=a,this.args=b,this.index=c,this.currentFileInfo=d},a.Call.prototype={type:"Call",accept:function(a){this.args=a.visit(this.args)},eval:function(b){var c,d,e=this.args.map(function(a){return a.eval(b)}),f=this.name.toLowerCase();if(f in a.functions)try{if(d=new a.functionCall(b,this.currentFileInfo),c=d[f].apply(d,e),null!=c)return c}catch(g){throw{type:g.type||"Runtime",message:"error evaluating function `"+this.name+"`"+(g.message?": "+g.message:""),index:this.index,filename:this.currentFileInfo.filename}}return new a.Call(this.name,e,this.index,this.currentFileInfo)},genCSS:function(a,b){b.add(this.name+"(",this.currentFileInfo,this.index);for(var c=0;cf;f++)e[f]=a.operate(b,c,this.rgb[f],d.rgb[f]);return new a.Color(e,this.alpha+d.alpha)},toRGB:function(){return"#"+this.rgb.map(function(a){return a=Math.round(a),a=(a>255?255:0>a?0:a).toString(16),1===a.length?"0"+a:a}).join("")},toHSL:function(){var a,b,c=this.rgb[0]/255,d=this.rgb[1]/255,e=this.rgb[2]/255,f=this.alpha,g=Math.max(c,d,e),h=Math.min(c,d,e),i=(g+h)/2,j=g-h;if(g===h)a=b=0;else{switch(b=i>.5?j/(2-g-h):j/(g+h),g){case c:a=(d-e)/j+(e>d?6:0);break;case d:a=(e-c)/j+2;break;case e:a=(c-d)/j+4}a/=6}return{h:360*a,s:b,l:i,a:f}},toHSV:function(){var a,b,c=this.rgb[0]/255,d=this.rgb[1]/255,e=this.rgb[2]/255,f=this.alpha,g=Math.max(c,d,e),h=Math.min(c,d,e),i=g,j=g-h;if(b=0===g?0:j/g,g===h)a=0;else{switch(g){case c:a=(d-e)/j+(e>d?6:0);break;case d:a=(e-c)/j+2;break;case e:a=(c-d)/j+4}a/=6}return{h:360*a,s:b,v:i,a:f}},toARGB:function(){var a=[Math.round(255*this.alpha)].concat(this.rgb);return"#"+a.map(function(a){return a=Math.round(a),a=(a>255?255:0>a?0:a).toString(16),1===a.length?"0"+a:a}).join("")},compare:function(a){return a.rgb?a.rgb[0]===this.rgb[0]&&a.rgb[1]===this.rgb[1]&&a.rgb[2]===this.rgb[2]&&a.alpha===this.alpha?0:-1:-1}},a.Color.fromKeyword=function(c){if(a.colors.hasOwnProperty(c))return new a.Color(a.colors[c].slice(1));if(c===b){var d=new a.Color([0,0,0],0);return d.isTransparentKeyword=!0,d}}}(require("../tree")),function(a){a.Comment=function(a,b,c,d){this.value=a,this.silent=!!b,this.currentFileInfo=d},a.Comment.prototype={type:"Comment",genCSS:function(b,c){this.debugInfo&&c.add(a.debugInfo(b,this),this.currentFileInfo,this.index),c.add(this.value.trim())},toCSS:a.toCSS,isSilent:function(a){var b=this.currentFileInfo&&this.currentFileInfo.reference&&!this.isReferenced,c=a.compress&&!this.value.match(/^\/\*!/);return this.silent||b||c},eval:function(){return this},markReferenced:function(){this.isReferenced=!0}}}(require("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype={type:"Condition",accept:function(a){this.lvalue=a.visit(this.lvalue),this.rvalue=a.visit(this.rvalue)},eval:function(a){var b,c=this.lvalue.eval(a),d=this.rvalue.eval(a),e=this.index;return b=function(a){switch(a){case"and":return c&&d;case"or":return c||d;default:if(c.compare)b=c.compare(d);else{if(!d.compare)throw{type:"Type",message:"Unable to perform comparison",index:e};b=d.compare(c)}switch(b){case-1:return"<"===a||"=<"===a||"<="===a;case 0:return"="===a||">="===a||"=<"===a||"<="===a;case 1:return">"===a||">="===a}}}(this.op),this.negate?!b:b}}}(require("../tree")),function(a){a.Dimension=function(b,c){this.value=parseFloat(b),this.unit=c&&c instanceof a.Unit?c:new a.Unit(c?[c]:void 0)},a.Dimension.prototype={type:"Dimension",accept:function(a){this.unit=a.visit(this.unit)},eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},genCSS:function(a,b){if(a&&a.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var c=this.value,d=String(c);if(0!==c&&1e-6>c&&c>-1e-6&&(d=c.toFixed(20).replace(/0+$/,"")),a&&a.compress){if(0===c&&this.unit.isLength())return b.add(d),void 0;c>0&&1>c&&(d=d.substr(1))}b.add(d),this.unit.genCSS(a,b)},toCSS:a.toCSS,operate:function(b,c,d){var e=a.operate(b,c,this.value,d.value),f=this.unit.clone();if("+"===c||"-"===c)if(0===f.numerator.length&&0===f.denominator.length)f.numerator=d.unit.numerator.slice(0),f.denominator=d.unit.denominator.slice(0);else if(0===d.unit.numerator.length&&0===f.denominator.length);else{if(d=d.convertTo(this.unit.usedUnits()),b.strictUnits&&d.unit.toString()!==f.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+f.toString()+"' and '"+d.unit.toString()+"'.");e=a.operate(b,c,this.value,d.value)}else"*"===c?(f.numerator=f.numerator.concat(d.unit.numerator).sort(),f.denominator=f.denominator.concat(d.unit.denominator).sort(),f.cancel()):"/"===c&&(f.numerator=f.numerator.concat(d.unit.denominator).sort(),f.denominator=f.denominator.concat(d.unit.numerator).sort(),f.cancel());return new a.Dimension(e,f)},compare:function(b){if(b instanceof a.Dimension){var c=this.unify(),d=b.unify(),e=c.value,f=d.value;return f>e?-1:e>f?1:d.unit.isEmpty()||0===c.unit.compare(d.unit)?0:-1}return-1},unify:function(){return this.convertTo({length:"m",duration:"s",angle:"rad"})},convertTo:function(b){var c,d,e,f,g,h=this.value,i=this.unit.clone(),j={};if("string"==typeof b){for(c in a.UnitConversions)a.UnitConversions[c].hasOwnProperty(b)&&(j={},j[c]=b);b=j}g=function(a,b){return e.hasOwnProperty(a)?(b?h/=e[a]/e[f]:h*=e[a]/e[f],f):a};for(d in b)b.hasOwnProperty(d)&&(f=b[d],e=a.UnitConversions[d],i.map(g));return i.cancel(),new a.Dimension(h,i)}},a.UnitConversions={length:{m:1,cm:.01,mm:.001,"in":.0254,pt:.0254/72,pc:12*(.0254/72)},duration:{s:1,ms:.001},angle:{rad:1/(2*Math.PI),deg:1/360,grad:.0025,turn:1}},a.Unit=function(a,b,c){this.numerator=a?a.slice(0).sort():[],this.denominator=b?b.slice(0).sort():[],this.backupUnit=c},a.Unit.prototype={type:"Unit",clone:function(){return new a.Unit(this.numerator.slice(0),this.denominator.slice(0),this.backupUnit)},genCSS:function(a,b){this.numerator.length>=1?b.add(this.numerator[0]):this.denominator.length>=1?b.add(this.denominator[0]):a&&a.strictUnits||!this.backupUnit||b.add(this.backupUnit)},toCSS:a.toCSS,toString:function(){var a,b=this.numerator.join("*");for(a=0;a0)for(b=0;e>b;b++)this.numerator.push(a);else if(0>e)for(b=0;-e>b;b++)this.denominator.push(a)}0===this.numerator.length&&0===this.denominator.length&&c&&(this.backupUnit=c),this.numerator.sort(),this.denominator.sort()}}}(require("../tree")),function(a){a.Directive=function(b,c,d,e){this.name=b,Array.isArray(c)?(this.rules=[new a.Ruleset([],c)],this.rules[0].allowImports=!0):this.value=c,this.currentFileInfo=e},a.Directive.prototype={type:"Directive",accept:function(a){this.rules=a.visit(this.rules),this.value=a.visit(this.value)},genCSS:function(b,c){c.add(this.name,this.currentFileInfo,this.index),this.rules?a.outputRuleset(b,c,this.rules):(c.add(" "),this.value.genCSS(b,c),c.add(";"))},toCSS:a.toCSS,eval:function(b){var c=this;return this.rules&&(b.frames.unshift(this),c=new a.Directive(this.name,null,this.index,this.currentFileInfo),c.rules=[this.rules[0].eval(b)],c.rules[0].root=!0,b.frames.shift()),c},variable:function(b){return a.Ruleset.prototype.variable.call(this.rules[0],b)},find:function(){return a.Ruleset.prototype.find.apply(this.rules[0],arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.rules[0])},markReferenced:function(){var a,b;if(this.isReferenced=!0,this.rules)for(b=this.rules[0].rules,a=0;a":" > ","|":"|"},_outputMapCompressed:{"":""," ":" ",":":" :","+":"+","~":"~",">":">","|":"|"},genCSS:function(a,b){b.add((a.compress?this._outputMapCompressed:this._outputMap)[this.value])},toCSS:a.toCSS}}(require("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={type:"Expression",accept:function(a){this.value=a.visit(this.value)},eval:function(b){var c,d=this.parens&&!this.parensInOp,e=!1;return d&&b.inParenthesis(),this.value.length>1?c=new a.Expression(this.value.map(function(a){return a.eval(b)})):1===this.value.length?(this.value[0].parens&&!this.value[0].parensInOp&&(e=!0),c=this.value[0].eval(b)):c=this,d&&b.outOfParenthesis(),this.parens&&this.parensInOp&&!b.isMathOn()&&!e&&(c=new a.Paren(c)),c},genCSS:function(a,b){for(var c=0;c0&&c.length&&""===c[0].combinator.value&&(c[0].combinator.value=" "),d=d.concat(a[b].elements);this.selfSelectors=[{elements:d}]}}}(require("../tree")),function(a){a.Import=function(a,b,c,d,e){if(this.options=c,this.index=d,this.path=a,this.features=b,this.currentFileInfo=e,void 0!==this.options.less||this.options.inline)this.css=!this.options.less||this.options.inline;else{var f=this.getPath();f&&/css([\?;].*)?$/.test(f)&&(this.css=!0)}},a.Import.prototype={type:"Import",accept:function(a){this.features=a.visit(this.features),this.path=a.visit(this.path),this.options.inline||(this.root=a.visit(this.root))},genCSS:function(a,b){this.css&&(b.add("@import ",this.currentFileInfo,this.index),this.path.genCSS(a,b),this.features&&(b.add(" "),this.features.genCSS(a,b)),b.add(";"))},toCSS:a.toCSS,getPath:function(){if(this.path instanceof a.Quoted){var b=this.path.value;return void 0!==this.css||/(\.[a-z]*$)|([\?;].*)$/.test(b)?b:b+".less"}return this.path instanceof a.URL?this.path.value.value:null},evalForImport:function(b){return new a.Import(this.path.eval(b),this.features,this.options,this.index,this.currentFileInfo)},evalPath:function(b){var c=this.path.eval(b),d=this.currentFileInfo&&this.currentFileInfo.rootpath;if(!(c instanceof a.URL)){if(d){var e=c.value;e&&b.isPathRelative(e)&&(c.value=d+e)}c.value=b.normalizePath(c.value)}return c},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.skip)return[];if(this.options.inline){var e=new a.Anonymous(this.root,0,{filename:this.importedFilename},!0);return this.features?new a.Media([e],this.features.value):[e]}if(this.css){var f=new a.Import(this.evalPath(b),d,this.options,this.index);if(!f.css&&this.error)throw this.error;return f}return c=new a.Ruleset([],this.root.rules.slice(0)),c.evalImports(b),this.features?new a.Media(c.rules,this.features.value):c.rules}}}(require("../tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={type:"JavaScript",eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify(new a.Variable("@"+e,d.index).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: "+g.message+" from `"+f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{c=f.call(e)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message+"'",index:this.index}}return"string"==typeof c?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(require("../tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={type:"Keyword",eval:function(){return this},genCSS:function(a,b){b.add(this.value)},toCSS:a.toCSS,compare:function(b){return b instanceof a.Keyword?b.value===this.value?0:1:-1}},a.True=new a.Keyword("true"),a.False=new a.Keyword("false")}(require("../tree")),function(a){a.Media=function(b,c,d,e){this.index=d,this.currentFileInfo=e;var f=this.emptySelectors();this.features=new a.Value(c),this.rules=[new a.Ruleset(f,b)],this.rules[0].allowImports=!0},a.Media.prototype={type:"Media",accept:function(a){this.features=a.visit(this.features),this.rules=a.visit(this.rules)},genCSS:function(b,c){c.add("@media ",this.currentFileInfo,this.index),this.features.genCSS(b,c),a.outputRuleset(b,c,this.rules)},toCSS:a.toCSS,eval:function(b){b.mediaBlocks||(b.mediaBlocks=[],b.mediaPath=[]);var c=new a.Media([],[],this.index,this.currentFileInfo);this.debugInfo&&(this.rules[0].debugInfo=this.debugInfo,c.debugInfo=this.debugInfo);var d=!1;b.strictMath||(d=!0,b.strictMath=!0);try{c.features=this.features.eval(b)}finally{d&&(b.strictMath=!1)}return b.mediaPath.push(c),b.mediaBlocks.push(c),b.frames.unshift(this.rules[0]),c.rules=[this.rules[0].eval(b)],b.frames.shift(),b.mediaPath.pop(),0===b.mediaPath.length?c.evalTop(b):c.evalNested(b)},variable:function(b){return a.Ruleset.prototype.variable.call(this.rules[0],b)},find:function(){return a.Ruleset.prototype.find.apply(this.rules[0],arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.rules[0])},emptySelectors:function(){var b=new a.Element("","&",this.index,this.currentFileInfo);return[new a.Selector([b],null,null,this.index,this.currentFileInfo)]},markReferenced:function(){var a,b=this.rules[0].rules;for(this.isReferenced=!0,a=0;a1){var d=this.emptySelectors();c=new a.Ruleset(d,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(0===a.length)return[];if(1===a.length)return a[0];for(var b=[],c=this.permute(a.slice(1)),d=0;d0){for(j=!0,g=0;gthis.params.length)return!1}c=Math.min(d,this.arity);for(var e=0;c>e;e++)if(!this.params[e].name&&!this.params[e].variadic&&a[e].value.eval(b).toCSS()!=this.params[e].value.eval(b).toCSS())return!1;return!0}}}(require("../tree")),function(a){a.Negative=function(a){this.value=a},a.Negative.prototype={type:"Negative",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add("-"),this.value.genCSS(a,b)},toCSS:a.toCSS,eval:function(b){return b.isMathOn()?new a.Operation("*",[new a.Dimension(-1),this.value]).eval(b):new a.Negative(this.value.eval(b))}}}(require("../tree")),function(a){a.Operation=function(a,b,c){this.op=a.trim(),this.operands=b,this.isSpaced=c},a.Operation.prototype={type:"Operation",accept:function(a){this.operands=a.visit(this.operands)},eval:function(b){var c,d=this.operands[0].eval(b),e=this.operands[1].eval(b);if(b.isMathOn()){if(d instanceof a.Dimension&&e instanceof a.Color){if("*"!==this.op&&"+"!==this.op)throw{type:"Operation",message:"Can't substract or divide a color from a number"};c=e,e=d,d=c}if(!d.operate)throw{type:"Operation",message:"Operation on an invalid type"};return d.operate(b,this.op,e)}return new a.Operation(this.op,[d,e],this.isSpaced)},genCSS:function(a,b){this.operands[0].genCSS(a,b),this.isSpaced&&b.add(" "),b.add(this.op),this.isSpaced&&b.add(" "),this.operands[1].genCSS(a,b)},toCSS:a.toCSS},a.operate=function(a,b,c,d){switch(b){case"+":return c+d;case"-":return c-d;case"*":return c*d;case"/":return c/d}}}(require("../tree")),function(a){a.Paren=function(a){this.value=a},a.Paren.prototype={type:"Paren",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add("("),this.value.genCSS(a,b),b.add(")")},toCSS:a.toCSS,eval:function(b){return new a.Paren(this.value.eval(b))}}}(require("../tree")),function(a){a.Quoted=function(a,b,c,d,e){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d,this.currentFileInfo=e},a.Quoted.prototype={type:"Quoted",genCSS:function(a,b){this.escaped||b.add(this.quote,this.currentFileInfo,this.index),b.add(this.value),this.escaped||b.add(this.quote)},toCSS:a.toCSS,eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return new a.JavaScript(e,c.index,!0).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=new a.Variable("@"+e,c.index,c.currentFileInfo).eval(b,!0);return f instanceof a.Quoted?f.value:f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},compare:function(a){if(!a.toCSS)return-1;var b=this.toCSS(),c=a.toCSS();return b===c?0:c>b?-1:1}}}(require("../tree")),function(a){a.Rule=function(b,c,d,e,f,g,h){this.name=b,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.merge=e,this.index=f,this.currentFileInfo=g,this.inline=h||!1,this.variable="@"===b.charAt(0)},a.Rule.prototype={type:"Rule",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add(this.name+(a.compress?":":": "),this.currentFileInfo,this.index);try{this.value.genCSS(a,b)}catch(c){throw c.index=this.index,c.filename=this.currentFileInfo.filename,c}b.add(this.important+(this.inline||a.lastRule&&a.compress?"":";"),this.currentFileInfo,this.index)},toCSS:a.toCSS,eval:function(b){var c=!1;"font"!==this.name||b.strictMath||(c=!0,b.strictMath=!0);try{return new a.Rule(this.name,this.value.eval(b),this.important,this.merge,this.index,this.currentFileInfo,this.inline)}finally{c&&(b.strictMath=!1)}},makeImportant:function(){return new a.Rule(this.name,this.value,"!important",this.merge,this.index,this.currentFileInfo,this.inline)}}}(require("../tree")),function(a){a.Ruleset=function(a,b,c){this.selectors=a,this.rules=b,this._lookups={},this.strictImports=c},a.Ruleset.prototype={type:"Ruleset",accept:function(a){if(this.paths)for(var b=0;bf.selectors[g].elements.length?Array.prototype.push.apply(e,f.find(new a.Selector(b.elements.slice(1)),c)):e.push(f);break}}),this._lookups[f]=e)},genCSS:function(b,c){var d,e,f,g,h,i=[],j=[],k=!0;b.tabLevel=b.tabLevel||0,this.root||b.tabLevel++;var l=b.compress?"":Array(b.tabLevel+1).join(" "),m=b.compress?"":Array(b.tabLevel).join(" ");for(d=0;d0&&this.mergeElementsOnToSelectors(r,i),f=0;f0&&(k[0].elements=k[0].elements.slice(0),k[0].elements.push(new a.Element(j.combinator,"",0,j.index,j.currentFileInfo))),s.push(k);else for(g=0;g0?(m=k.slice(0),q=m.pop(),o=d.createDerived(q.elements.slice(0)),p=!1):o=d.createDerived([]),l.length>1&&(n=n.concat(l.slice(1))),l.length>0&&(p=!1,o.elements.push(new a.Element(j.combinator,l[0].elements[0].value,j.index,j.currentFileInfo)),o.elements=o.elements.concat(l[0].elements.slice(1))),p||m.push(o),m=m.concat(n),s.push(m);i=s,r=[]}for(r.length>0&&this.mergeElementsOnToSelectors(r,i),e=0;e0&&b.push(i[e])}else if(c.length>0)for(e=0;e0?e[e.length-1]=e[e.length-1].createDerived(e[e.length-1].elements.concat(b)):e.push(new a.Selector(b))}}}(require("../tree")),function(a){a.Selector=function(a,b,c,d,e,f){this.elements=a,this.extendList=b||[],this.condition=c,this.currentFileInfo=e||{},this.isReferenced=f,c||(this.evaldCondition=!0)},a.Selector.prototype={type:"Selector",accept:function(a){this.elements=a.visit(this.elements),this.extendList=a.visit(this.extendList),this.condition=a.visit(this.condition)},createDerived:function(b,c,d){d=null!=d?d:this.evaldCondition;var e=new a.Selector(b,c||this.extendList,this.condition,this.index,this.currentFileInfo,this.isReferenced);return e.evaldCondition=d,e},match:function(a){var b,c,d,e,f=this.elements,g=f.length;if(b=a.elements.slice(a.elements.length&&"&"===a.elements[0].value?1:0),c=b.length,d=Math.min(g,c),0===c||c>g)return!1;for(e=0;d>e;e++)if(f[e].value!==b[e].value)return!1;return!0},eval:function(a){var b=this.condition&&this.condition.eval(a);return this.createDerived(this.elements.map(function(b){return b.eval(a)}),this.extendList.map(function(b){return b.eval(a)}),b)},genCSS:function(a,b){var c,d;if(a&&a.firstSelector||""!==this.elements[0].combinator.value||b.add(" ",this.currentFileInfo,this.index),!this._css)for(c=0;c0)&&e.splice(0,0,b);else{b.paths=b.paths.filter(function(b){var c;for(" "===b[0].elements[0].combinator.value&&(b[0].elements[0].combinator=new a.Combinator("")),c=0;c0&&b.accept(this._visitor),c.visitDeeper=!1,this._mergeRules(b.rules),this._removeDuplicateRules(b.rules),b.rules.length>0&&b.paths.length>0&&e.splice(0,0,b)}return 1===e.length?e[0]:e},_removeDuplicateRules:function(b){var c,d,e,f={};for(e=b.length-1;e>=0;e--)if(d=b[e],d instanceof a.Rule)if(f[d.name]){c=f[d.name],c instanceof a.Rule&&(c=f[d.name]=[f[d.name].toCSS(this._env)]);var g=d.toCSS(this._env);-1!==c.indexOf(g)?b.splice(e,1):c.push(g)}else f[d.name]=d},_mergeRules:function(b){for(var c,d,e,f={},g=0;g1&&(d=c[0],d.value=new a.Value(c.map(function(a){return a.value})))})}}}(require("./tree")),function(a){a.extendFinderVisitor=function(){this._visitor=new a.visitor(this),this.contexts=[],this.allExtendsStack=[[]]},a.extendFinderVisitor.prototype={run:function(a){return a=this._visitor.visit(a),a.allExtends=this.allExtendsStack[0],a},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitRuleset:function(b){if(!b.root){var c,d,e,f,g=[];for(c=0;c100){var o="{unable to calculate}",p="{unable to calculate}";try{o=m[0].selfSelectors[0].toCSS(),p=m[0].selector.toCSS()}catch(q){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+o+":extend("+p+")"}}return m.concat(n.doExtendChaining(m,c,d+1))}return m},inInheritanceChain:function(a,b){if(a===b)return!0;if(b.parents){if(this.inInheritanceChain(a,b.parents[0]))return!0;if(this.inInheritanceChain(a,b.parents[1]))return!0}return!1},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitSelector:function(a,b){b.visitDeeper=!1},visitRuleset:function(a){if(!a.root){var b,c,d,e,f=this.allExtendsStack[this.allExtendsStack.length-1],g=[],h=this;for(d=0;d0&&k[i.matched].combinator.value!==g?i=null:i.matched++,i&&(i.finished=i.matched===k.length,i.finished&&!a.allowAfter&&(e+1j&&k>0&&(l[l.length-1].elements=l[l.length-1].elements.concat(c[j].elements.slice(k)),k=0,j++),i=f.elements.slice(k,h.index).concat([g]).concat(d.elements.slice(1)),j===h.pathIndex&&e>0?l[l.length-1].elements=l[l.length-1].elements.concat(i):(l=l.concat(c.slice(j,h.pathIndex)),l.push(new a.Selector(i))),j=h.endPathIndex,k=h.endPathElementIndex,k>=c[j].elements.length&&(k=0,j++);return j0&&(l[l.length-1].elements=l[l.length-1].elements.concat(c[j].elements.slice(k)),j++),l=l.concat(c.slice(j,c.length))},visitRulesetOut:function(){},visitMedia:function(a){var b=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);b=b.concat(this.doExtendChaining(b,a.allExtends)),this.allExtendsStack.push(b)},visitMediaOut:function(){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(a){var b=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);b=b.concat(this.doExtendChaining(b,a.allExtends)),this.allExtendsStack.push(b)},visitDirectiveOut:function(){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(require("./tree")),function(a){a.sourceMapOutput=function(a){this._css=[],this._rootNode=a.rootNode,this._writeSourceMap=a.writeSourceMap,this._contentsMap=a.contentsMap,this._sourceMapFilename=a.sourceMapFilename,this._outputFilename=a.outputFilename,this._sourceMapBasepath=a.sourceMapBasepath,this._sourceMapRootpath=a.sourceMapRootpath,this._outputSourceFiles=a.outputSourceFiles,this._sourceMapGeneratorConstructor=a.sourceMapGenerator||require("source-map").SourceMapGenerator,this._sourceMapRootpath&&"/"!==this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1)&&(this._sourceMapRootpath+="/"),this._lineNumber=0,this._column=0},a.sourceMapOutput.prototype.normalizeFilename=function(a){return this._sourceMapBasepath&&0===a.indexOf(this._sourceMapBasepath)&&(a=a.substring(this._sourceMapBasepath.length),("\\"===a.charAt(0)||"/"===a.charAt(0))&&(a=a.substring(1))),(this._sourceMapRootpath||"")+a.replace(/\\/g,"/")},a.sourceMapOutput.prototype.add=function(a,b,c,d){if(a){var e,f,g,h,i;if(b){var j=this._contentsMap[b.filename].substring(0,c);f=j.split("\n"),h=f[f.length-1]}if(e=a.split("\n"),g=e[e.length-1],b)if(d)for(i=0;i0){var c,d=JSON.stringify(this._sourceMapGenerator.toJSON());this._sourceMapFilename&&(c=this.normalizeFilename(this._sourceMapFilename)),this._writeSourceMap?this._writeSourceMap(d):c="data:application/json,"+encodeURIComponent(d),c&&this._css.push("/*# sourceMappingURL="+c+" */")}return this._css.join("")}}(require("./tree"));var isFileProtocol=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);less.env=less.env||("127.0.0.1"==location.hostname||"0.0.0.0"==location.hostname||"localhost"==location.hostname||location.port.length>0||isFileProtocol?"development":"production");var logLevel={info:2,errors:1,none:0};if(less.logLevel="undefined"!=typeof less.logLevel?less.logLevel:logLevel.info,less.async=less.async||!1,less.fileAsync=less.fileAsync||!1,less.poll=less.poll||(isFileProtocol?1e3:1500),less.functions)for(var func in less.functions)less.tree.functions[func]=less.functions[func];var dumpLineNumbers=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);dumpLineNumbers&&(less.dumpLineNumbers=dumpLineNumbers[1]);var typePattern=/^text\/(x-)?less$/,cache=null,fileCache={};if(less.watch=function(){return less.watchMode||(less.env="development",initRunningMode()),this.watchMode=!0},less.unwatch=function(){return clearInterval(less.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&less.watch(),"development"!=less.env)try{cache="undefined"==typeof window.localStorage?null:window.localStorage}catch(_){}var links=document.getElementsByTagName("link");less.sheets=[];for(var i=0;i + * Licensed under the Apache v2 License. + * + * @licence + */ + + + +(function (window, undefined) {// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + + +if (typeof(window.less) === 'undefined' || typeof(window.less.nodeType) !== 'undefined') { window.less = {}; } +less = window.less; +tree = window.less.tree = {}; +less.mode = 'browser'; + +var less, tree; + +// Node.js does not have a header file added which defines less +if (less === undefined) { + less = exports; + tree = require('./tree'); + less.mode = 'node'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser, + rootFilename = env && env.filename; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed around by reference. + if (!(env instanceof tree.parseEnv)) { + env = new tree.parseEnv(env); + } + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, currentFileInfo, importOptions, callback) { + var parserImports = this; + this.queue.push(path); + + var fileParsedFunc = function (e, root, fullPath) { + parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue + + var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename; + + parserImports.files[fullPath] = root; // Store the root + + if (e && !parserImports.error) { parserImports.error = e; } + + callback(e, root, importedPreviously, fullPath); + }; + + if (less.Parser.importer) { + less.Parser.importer(path, currentFileInfo, fileParsedFunc, env); + } else { + less.Parser.fileLoader(path, currentFileInfo, function(e, contents, fullPath, newFileInfo) { + if (e) {fileParsedFunc(e); return;} + + var newEnv = new tree.parseEnv(env); + + newEnv.currentFileInfo = newFileInfo; + newEnv.processImports = false; + newEnv.contents[fullPath] = contents; + + if (currentFileInfo.reference || importOptions.reference) { + newFileInfo.reference = true; + } + + if (importOptions.inline) { + fileParsedFunc(null, contents, fullPath); + } else { + new(less.Parser)(newEnv).parse(contents, function (e, root) { + fileParsedFunc(e, root, fullPath); + }); + } + }, env); + } + } + }; + + function save() { temp = chunks[j], memo = i, current = i; } + function restore() { chunks[j] = temp, i = memo, current = i; } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, length; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break; } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return tok.test(chunks[j]); + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, inputStream) { + var n = index + 1, + line = null, + column = -1; + + while (--n >= 0 && inputStream.charAt(n) !== '\n') { + column++; + } + + if (typeof index === 'number') { + line = (inputStream.slice(0, index).match(/\n/g) || "").length; + } + + return { + line: line, + column: column + }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + callLine = e.call && getLocation(e.call, input).line, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = callLine + 1; + this.callExtract = lines[callLine]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, line, lines, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + parser.imports.contents[env.currentFileInfo.filename] = input; + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': + if (!inParam) { + level++; + chunk.push(c); + break; + } + /* falls through */ + case '}': + if (!inParam) { + level--; + chunk.push(c); + chunks[++j] = chunk = []; + break; + } + /* falls through */ + case '(': + if (!inParam) { + inParam = true; + chunk.push(c); + break; + } + /* falls through */ + case ')': + if (inParam) { + inParam = false; + chunk.push(c); + break; + } + /* falls through */ + default: + chunk.push(c); + } + + i++; + } + if (level !== 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join(''); }); + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + return function (options, variables) { + options = options || {}; + var evaldRoot, + css, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, null, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + new(tree.toCSSVisitor)({compress: Boolean(options.compress)}) + .run(evaldRoot); + + if (options.sourceMap) { + evaldRoot = new tree.sourceMapOutput( + { + writeSourceMap: options.writeSourceMap, + rootNode: evaldRoot, + contentsMap: parser.imports.contents, + sourceMapFilename: options.sourceMapFilename, + sourceMapURL: options.sourceMapURL, + outputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath, + outputSourceFiles: options.outputSourceFiles, + sourceMapGenerator: options.sourceMapGenerator + }); + } + + css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.cleancss && less.mode === 'node') { + var CleanCSS = require('clean-css'); + //TODO would be nice for no advanced to be an option + return new CleanCSS({keepSpecialComments: '*', processImport: false, noRebase: true, noAdvanced: true}).minify(css); + } else if (options.compress) { + return css.replace(/(^(\s)+)|((\s)+$)/g, ""); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + var loc = getLocation(i, input); + lines = input.split('\n'); + line = loc.line + 1; + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: loc.column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + return callback(e); + } + else { + return callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + return finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') { return; } + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true, i, env.currentFileInfo); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment, false, i, env.currentFileInfo); + } + }, + + comments: function () { + var comment, comments = []; + + while(comment = $(this.comment)) { + comments.push(comment); + } + + return comments; + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true; } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { return; } + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + var color = tree.Color.fromKeyword(k); + if (color) { + return color; + } + return new(tree.Keyword)(k); + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) { return; } + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null; } + else { i += name.length; } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { + break; + } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) { + return; + } + + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + /*jshint eqnull:true */ + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) { + return; + } + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings + if (input.charAt(j) !== '`') { return; } + if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) { + error("You are using JavaScript, which has been disabled."); + } + + if (e) { $('~'); } + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")); + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return; } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i, env.currentFileInfo)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comments); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) { + return; + } + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comments); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) { return; } + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i, env.currentFileInfo); } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++; } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + // + // A CSS selector (see selector below) + // with less extensions e.g. the ability to extend and guard + // + lessSelector: function () { + return this.selector(true); + }, + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function (isLess) { + var e, elements = [], c, extend, extendList = [], when, condition; + + while ((isLess && (extend = $(this.extend))) || (isLess && (when = $(/^when/))) || (e = $(this.element))) { + if (when) { + condition = expect(this.conditions, 'expected condition'); + } else if (condition) { + error("CSS guard can only be used at the end of selector"); + } else if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e); + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { + break; + } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList, condition, i, env.currentFileInfo); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var key, val, op; + + if (! $('[')) { return; } + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[0-9]+%/) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + while (s = $(this.lessSelector)) { + selectors.push(s); + $(this.comments); + if (! $(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + $(this.comments); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) { + ruleset.debugInfo = debugInfo; + } + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, merge = false; + save(); + + if (c === '.' || c === '#' || c === '&') { return; } + + if (name = $(this.variable) || $(this.ruleProperty)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + + important = $(this.important); + if (name[name.length-1] === "+") { + merge = true; + name = name.substr(0, name.length - 1); + } + + if (value && $(this.end)) { + return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break; } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once|inline|reference)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = ($(this.entities.keyword) || $(this.entities.variable))) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null; } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break; } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break; } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + media.debugInfo = debugInfo; + } + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression, identifier; + + if (input.charAt(i) !== '@') { return; } + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) { return; } + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@host": + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + identifier = ($(/^[^{]+/) || '').trim(); + if (identifier) { + name += " " + identifier; + } + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules, i, env.currentFileInfo); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = []; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while (peek(/^,\s*(not\s*)?\(/) && $(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true; } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|<=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-'); } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = []; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + }, + ruleProperty: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/)) { + return name[1] + (name[2] || ""); + } + } + } + }; +}; + + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; } + else if (h * 2 < 1) { return m2; } + else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; } + else { return m1; } + } + + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + // filter: saturate(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + /*jshint loopfunc:true */ + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + if(!(val instanceof tree.Dimension)) { + throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") }; + } + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + /*jshint eqnull:true */ + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + _minmax: function (isMin, args) { + args = Array.prototype.slice.call(args); + switch(args.length) { + case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 1: return args[0]; + } + var i, j, current, currentUnified, referenceUnified, unit, + order = [], // elems only contains original argument values. + values = {}; // key is the unit.toString() for unified tree.Dimension values, + // value is the index into the order array. + for (i = 0; i < args.length; i++) { + current = args[i]; + if (!(current instanceof tree.Dimension)) { + order.push(current); + continue; + } + currentUnified = current.unify(); + unit = currentUnified.unit.toString(); + j = values[unit]; + if (j === undefined) { + values[unit] = order.length; + order.push(current); + continue; + } + referenceUnified = order[j].unify(); + if ( isMin && currentUnified.value < referenceUnified.value || + !isMin && currentUnified.value > referenceUnified.value) { + order[j] = current; + } + } + if (order.length == 1) { + return order[0]; + } + args = order.map(function (a) { return a.toCSS(this.env); }) + .join(this.env.compress ? "," : ", "); + return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")"); + }, + min: function () { + return this._minmax(true, arguments); + }, + max: function () { + return this._minmax(false, arguments); + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + var colorCandidate = n.value, + returnColor; + returnColor = tree.Color.fromKeyword(colorCandidate); + if (returnColor) { + return returnColor; + } + if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) { + return new(tree.Color)(colorCandidate.slice(1)); + } + throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" }; + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + // handle non-array values as an array of length 1 + // return 'undefined' if index is invalid + return Array.isArray(values.value) + ? values.value[index] : Array(values)[index]; + }, + length: function(values) { + var n = Array.isArray(values.value) ? values.value.length : 1; + return new tree.Dimension(n); + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) { mimetype += ';base64'; } + } + else { + useBase64 = /;base64$/.test(mimetype); + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + }, + + "svg-gradient": function(direction) { + + function throwArgumentDescriptor() { + throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" }; + } + + if (arguments.length < 3) { + throwArgumentDescriptor(); + } + var stops = Array.prototype.slice.call(arguments, 1), + gradientDirectionSvg, + gradientType = "linear", + rectangleDimension = 'x="0" y="0" width="1" height="1"', + useBase64 = true, + renderEnv = {compress: false}, + returner, + directionValue = direction.toCSS(renderEnv), + i, color, position, positionValue, alpha; + + switch (directionValue) { + case "to bottom": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; + break; + case "to right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; + break; + case "to bottom right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; + break; + case "to top right": + gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; + break; + case "ellipse": + case "ellipse at center": + gradientType = "radial"; + gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; + rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; + break; + default: + throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" }; + } + returner = '' + + '' + + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; + + for (i = 0; i < stops.length; i+= 1) { + if (stops[i].value) { + color = stops[i].value[0]; + position = stops[i].value[1]; + } else { + color = stops[i]; + position = undefined; + } + + if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) { + throwArgumentDescriptor(); + } + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + alpha = color.alpha; + returner += ''; + } + returner += '' + + ''; + + if (useBase64) { + // only works in node, needs interface to what is supported in environment + try { + returner = new Buffer(returner).toString('base64'); + } catch(e) { + useBase64 = false; + } + } + + returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'"; + return new(tree.URL)(new(tree.Anonymous)(returner)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + /*jshint eqnull:true */ + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); + +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); + +(function (tree) { + +tree.debugInfo = function(env, ctx, lineSeperator) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) { + if (a == '\\') { + a = '\/'; + } + return '\\' + a; + }) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r; } + } + return null; +}; + +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +tree.toCSS = function (env) { + var strs = []; + this.genCSS(env, { + add: function(chunk, fileInfo, index) { + strs.push(chunk); + }, + isEmpty: function () { + return strs.length === 0; + } + }); + return strs.join(''); +}; + +tree.outputRuleset = function (env, output, rules) { + output.add((env.compress ? '{' : ' {\n')); + env.tabLevel = (env.tabLevel || 0) + 1; + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + for(var i = 0; i < rules.length; i++) { + output.add(tabRuleStr); + rules[i].genCSS(env, output); + output.add(env.compress ? '' : '\n'); + } + env.tabLevel--; + output.add(tabSetStr + "}"); +}; + +})(require('./tree')); + +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); } + return this; + }, + genCSS: function (env, output) { + output.add("alpha(opacity="); + + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + + output.add(")"); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Anonymous = function (string, index, currentFileInfo, mapLines) { + this.value = string.value || string; + this.index = index; + this.mapLines = mapLines; + this.currentFileInfo = currentFileInfo; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + eval: function () { return this; }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + }, + genCSS: function (env, output) { + output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add(this.key + '='); + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + /*jshint eqnull:true */ + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + return new tree.Call(this.name, args, this.index, this.currentFileInfo); + }, + + genCSS: function (env, output) { + output.add(this.name + "(", this.currentFileInfo, this.index); + + for(var i = 0; i < this.args.length; i++) { + this.args[i].genCSS(env, output); + if (i + 1 < this.args.length) { + output.add(", "); + } + } + + output.add(")"); + }, + + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; + +var transparentKeyword = "transparent"; + +tree.Color.prototype = { + type: "Color", + eval: function () { return this; }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + if (this.alpha < 1.0) { + if (this.alpha === 0 && this.isTransparentKeyword) { + return transparentKeyword; + } + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.toRGB(); + + if (compress) { + var splitcolor = color.split(''); + + // Convert color to short format + if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) { + color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5]; + } + } + + return color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toRGB: function () { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + +tree.Color.fromKeyword = function(keyword) { + if (tree.colors.hasOwnProperty(keyword)) { + // detect named color + return new(tree.Color)(tree.colors[keyword].slice(1)); + } + if (keyword === transparentKeyword) { + var transparent = new(tree.Color)([0, 0, 0], 0); + transparent.isTransparentKeyword = true; + return transparent; + } +}; + + +})(require('../tree')); + +(function (tree) { + +tree.Comment = function (value, silent, index, currentFileInfo) { + this.value = value; + this.silent = !!silent; + this.currentFileInfo = currentFileInfo; +}; +tree.Comment.prototype = { + type: "Comment", + genCSS: function (env, output) { + if (this.debugInfo) { + output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index); + } + output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n + }, + toCSS: tree.toCSS, + isSilent: function(env) { + var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced), + isCompressed = env.compress && !this.value.match(/^\/\*!/); + return this.silent || isReference || isCompressed; + }, + eval: function () { return this; }, + markReferenced: function () { + this.isReferenced = true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<' || op === '<='; + case 0: return op === '=' || op === '>=' || op === '=<' || op === '<='; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); + +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + genCSS: function (env, output) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && this.unit.isLength()) { + output.add(strValue); + return; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + output.add(strValue); + this.unit.genCSS(env, output); + }, + toCSS: tree.toCSS, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + /*jshint noempty:false */ + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, targetUnit, derivedConversions = {}, applyUnit; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + applyUnit = function (atomicUnit, denominator) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(applyUnit); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + genCSS: function (env, output) { + if (this.numerator.length >= 1) { + output.add(this.numerator[0]); + } else + if (this.denominator.length >= 1) { + output.add(this.denominator[0]); + } else + if ((!env || !env.strictUnits) && this.backupUnit) { + output.add(this.backupUnit); + } + }, + toCSS: tree.toCSS, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isLength: function () { + return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/)); + }, + + isEmpty: function () { + return this.numerator.length === 0 && this.denominator.length === 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length === 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, result = {}, mapUnit; + + mapUnit = function (atomicUnit) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }; + + for (var groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(mapUnit); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Directive = function (name, value, index, currentFileInfo) { + this.name = name; + + if (Array.isArray(value)) { + this.rules = [new(tree.Ruleset)([], value)]; + this.rules[0].allowImports = true; + } else { + this.value = value; + } + this.currentFileInfo = currentFileInfo; + +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.rules = visitor.visit(this.rules); + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name, this.currentFileInfo, this.index); + if (this.rules) { + tree.outputRuleset(env, output, this.rules); + } else { + output.add(' '); + this.value.genCSS(env, output); + output.add(';'); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var evaldDirective = this; + if (this.rules) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo); + evaldDirective.rules = [this.rules[0].eval(env)]; + evaldDirective.rules[0].root = true; + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + markReferenced: function () { + var i, rules; + this.isReferenced = true; + if (this.rules) { + rules = this.rules[0].rules; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Element = function (combinator, value, index, currentFileInfo) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index, + this.currentFileInfo); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env), this.currentFileInfo, this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value === '' && this.combinator.value.charAt(0) === '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + _outputMap: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : ' + ', + '~' : ' ~ ', + '>' : ' > ', + '|' : '|' + }, + _outputMapCompressed: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : '+', + '~' : '~', + '>' : '>', + '|' : '|' + }, + genCSS: function (env, output) { + output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + genCSS: function (env, output) { + for(var i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add(" "); + } + } + }, + toCSS: tree.toCSS, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i, + selectorElements; + + for(i = 0; i < selectors.length; i++) { + selectorElements = selectors[i].elements; + // duplicate the logic in genCSS function inside the selector node. + // future TODO - move both logics into the selector joiner visitor + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + selectorElements[0].combinator.value = ' '; + } + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); + +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined || this.options.inline) { + this.css = !this.options.less || this.options.inline; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + if (!this.options.inline) { + this.root = visitor.visit(this.root); + } + }, + genCSS: function (env, output) { + if (this.css) { + output.add("@import ", this.currentFileInfo, this.index); + this.path.genCSS(env, output); + if (this.features) { + output.add(" "); + this.features.genCSS(env, output); + } + output.add(';'); + } + }, + toCSS: tree.toCSS, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + + if (!(path instanceof tree.URL)) { + if (rootpath) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + path.value = env.normalizePath(path.value); + } + + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.options.inline) { + //todo needs to reference css file not import + var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true); + return this.features ? new(tree.Media)([contents], this.features.value) : [contents]; + } else if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + /*jshint loopfunc:true */ + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Keyword = function (value) { this.value = value; }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); + +(function (tree) { + +tree.Media = function (value, features, index, currentFileInfo) { + this.index = index; + this.currentFileInfo = currentFileInfo; + + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.rules = [new(tree.Ruleset)(selectors, value)]; + this.rules[0].allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.rules = visitor.visit(this.rules); + }, + genCSS: function (env, output) { + output.add('@media ', this.currentFileInfo, this.index); + this.features.genCSS(env, output); + tree.outputRuleset(env, output, this.rules); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], [], this.index, this.currentFileInfo); + if(this.debugInfo) { + this.rules[0].debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.rules[0]); + media.rules = [this.rules[0].eval(env)]; + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env); + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', this.index, this.currentFileInfo); + return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)]; + }, + markReferenced: function () { + var i, rules = this.rules[0].rules; + this.isReferenced = true; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])]; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + if (!(mixin instanceof tree.mixin.Definition)) { + mixin = new tree.mixin.Definition("", [], mixin.rules, null, false); + mixin.originalRuleset = mixins[m].originalRuleset || mixins[m]; + } + //if (this.important) { + // isImportant = env.isImportant; + // env.isImportant = true; + //} + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + //if (this.important) { + // env.isImportant = isImportant; + //} + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + if (!this.currentFileInfo || !this.currentFileInfo.reference) { + for (i = 0; i < rules.length; i++) { + rule = rules[i]; + if (rule.markReferenced) { + rule.markReferenced(); + } + } + } + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1; } + else { return count; } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + /*jshint boss:true */ + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) { continue; } + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + rules, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules); + ruleset.originalRuleset = this; + ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames))); + if (important) { + ruleset = this.parent.makeImportant.apply(ruleset); + } + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables + .concat(this.frames) // the parent namespace/mixin frames + .concat(env.frames)))) { // the current environment frames + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (! this.variadic) { + if (argsLength < this.required) { return false; } + if (argsLength > this.params.length) { return false; } + } else { + if (argsLength < (this.required - 1)) { return false; } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('-'); + this.value.genCSS(env, output); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + genCSS: function (env, output) { + this.operands[0].genCSS(env, output); + if (this.isSpaced) { + output.add(" "); + } + output.add(this.op); + if (this.isSpaced) { + output.add(" "); + } + this.operands[1].genCSS(env, output); + }, + toCSS: tree.toCSS +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('('); + this.value.genCSS(env, output); + output.add(')'); + }, + toCSS: tree.toCSS, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + genCSS: function (env, output) { + if (!this.escaped) { + output.add(this.quote, this.currentFileInfo, this.index); + } + output.add(this.value); + if (!this.escaped) { + output.add(this.quote); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (name.charAt(0) === '@'); +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index); + try { + this.value.genCSS(env, output); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index); + }, + toCSS: tree.toCSS, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.merge, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.merge, + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + if (this.paths) { + for(var i = 0; i < this.paths.length; i++) { + this.paths[i] = visitor.visit(this.paths[i]); + } + } else { + this.selectors = visitor.visit(this.selectors); + } + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env); }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + var rule; + var i; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + /*jshint loopfunc:true */ + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (i = 0; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + matchCondition: function (args, env) { + var lastSelector = this.selectors[this.selectors.length-1]; + if (lastSelector.condition && + !lastSelector.condition.eval( + new(tree.evalEnv)(env, + env.frames))) { + return false; + } + return true; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables; } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key]; } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > match) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(match)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + genCSS: function (env, output) { + var i, j, + ruleNodes = [], + rulesetNodes = [], + debugInfo, // Line number debugging + rule, + firstRuleset = true, + path; + + env.tabLevel = (env.tabLevel || 0); + + if (!this.root) { + env.tabLevel++; + } + + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + + for (i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + if (rule.rules || (rule instanceof tree.Media) || rule instanceof tree.Directive || (this.root && rule instanceof tree.Comment)) { + rulesetNodes.push(rule); + } else { + ruleNodes.push(rule); + } + } + + // If this is the root node, we don't render + // a selector, or {}. + if (!this.root) { + debugInfo = tree.debugInfo(env, this, tabSetStr); + + if (debugInfo) { + output.add(debugInfo); + output.add(tabSetStr); + } + + for(i = 0; i < this.paths.length; i++) { + path = this.paths[i]; + env.firstSelector = true; + for(j = 0; j < path.length; j++) { + path[j].genCSS(env, output); + env.firstSelector = false; + } + if (i + 1 < this.paths.length) { + output.add(env.compress ? ',' : (',\n' + tabSetStr)); + } + } + + output.add((env.compress ? '{' : ' {\n') + tabRuleStr); + } + + // Compile rules and rulesets + for (i = 0; i < ruleNodes.length; i++) { + rule = ruleNodes[i]; + + // @page{ directive ends up with root elements inside it, a mix of rules and rulesets + // In this instance we do not know whether it is the last property + if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) { + env.lastRule = true; + } + + if (rule.genCSS) { + rule.genCSS(env, output); + } else if (rule.value) { + output.add(rule.value.toString()); + } + + if (!env.lastRule) { + output.add(env.compress ? '' : ('\n' + tabRuleStr)); + } else { + env.lastRule = false; + } + } + + if (!this.root) { + output.add((env.compress ? '}' : '\n' + tabSetStr + '}')); + env.tabLevel--; + } + + for (i = 0; i < rulesetNodes.length; i++) { + if (ruleNodes.length && firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + if (!firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + firstRuleset = false; + rulesetNodes[i].genCSS(env, output); + } + + if (!output.isEmpty() && !env.compress && this.firstRoot) { + output.add('\n'); + } + }, + + toCSS: tree.toCSS, + + markReferenced: function () { + for (var s = 0; s < this.selectors.length; s++) { + this.selectors[s].markReferenced(); + } + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for (i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for (j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length === 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0, el.index, el.currentFileInfo)); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for (k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = selector.createDerived([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for (i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length === 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for (i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); + +(function (tree) { + +tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) { + this.elements = elements; + this.extendList = extendList || []; + this.condition = condition; + this.currentFileInfo = currentFileInfo || {}; + this.isReferenced = isReferenced; + if (!condition) { + this.evaldCondition = true; + } +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList); + this.condition = visitor.visit(this.condition); + }, + createDerived: function(elements, extendList, evaldCondition) { + /*jshint eqnull:true */ + evaldCondition = evaldCondition != null ? evaldCondition : this.evaldCondition; + var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced); + newSelector.evaldCondition = evaldCondition; + return newSelector; + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return 0; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return 0; + } + } + } + return max; // return number of matched selectors + }, + eval: function (env) { + var evaldCondition = this.condition && this.condition.eval(env); + + return this.createDerived(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + }), evaldCondition); + }, + genCSS: function (env, output) { + var i, element; + if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") { + output.add(' ', this.currentFileInfo, this.index); + } + if (!this._css) { + //TODO caching? speed comparison? + for(i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(env, output); + } + } + }, + toCSS: tree.toCSS, + markReferenced: function () { + this.isReferenced = true; + }, + getIsReferenced: function() { + return !this.currentFileInfo.reference || this.isReferenced; + }, + getIsOutput: function() { + return this.evaldCondition; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + eval: function () { return this; } +}; + +})(require('../tree')); + +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add("url("); + this.value.genCSS(env, output); + output.add(")"); + }, + toCSS: tree.toCSS, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + val.value = ctx.normalizePath(val.value); + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + genCSS: function (env, output) { + var i; + for(i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i+1 < this.value.length) { + output.add((env && env.compress) ? ',' : ', '); + } + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { + this.name = name; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') === 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); + +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'rootpath', // option - rootpath to append to URL's + 'strictImports', // option - + 'insecure', // option - whether to allow imports from insecure ssl hosts + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true + 'mime', // browser only - mime type for sheet import + 'useFileCache', // browser only - whether to use the per file session cache + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' - absolute path to the entry file + // 'reference' - whether the file should not be output and only output parts that are referenced + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'cleancss', // whether to compress with clean-css + 'sourceMap', // whether to output a source map + 'importMultiple'// whether we are currently importing multiple copies + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + tree.evalEnv.prototype.normalizePath = function( path ) { + var + segments = path.split("/").reverse(), + segment; + + path = []; + while (segments.length !== 0 ) { + segment = segments.pop(); + switch( segment ) { + case ".": + break; + case "..": + if ((path.length === 0) || (path[path.length - 1] === "..")) { + path.push( segment ); + } else { + path.pop(); + } + break; + default: + path.push( segment ); + break; + } + } + + return path.join("/"); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + evald = this.flatten(evald); + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + }, + doAccept: function (node) { + node.accept(this); + }, + flatten: function(arr, master) { + return arr.reduce(this.flattenReduce.bind(this), master || []); + }, + flattenReduce: function(sum, element) { + if (element instanceof Array) { + sum = this.flatten(element, sum); + } else { + sum.push(element); + } + return sum; + } + }; + +})(require('./tree')); +(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode, + inlineCSS = importNode.options.inline; + + if (!importNode.css || inlineCSS) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + + if (importNode.options.multiple) { + env.importMultiple = true; + } + + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + + if (imported && !env.importMultiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + importNode.importedFilename = fullPath; + if (!inlineCSS && !importNode.skip) { + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + return; + } + } + + subFinish(); + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree')); +(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.selectors = rulesetNode.selectors.filter(function(selector) { return selector.getIsOutput(); }); + if (rulesetNode.selectors.length === 0) { + rulesetNode.rules.length = 0; + } + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree')); +(function (tree) { + tree.toCSSVisitor = function(env) { + this._visitor = new tree.visitor(this); + this._env = env; + }; + + tree.toCSSVisitor.prototype = { + isReplacing: true, + run: function (root) { + return this._visitor.visit(root); + }, + + visitRule: function (ruleNode, visitArgs) { + if (ruleNode.variable) { + return []; + } + return ruleNode; + }, + + visitMixinDefinition: function (mixinNode, visitArgs) { + return []; + }, + + visitExtend: function (extendNode, visitArgs) { + return []; + }, + + visitComment: function (commentNode, visitArgs) { + if (commentNode.isSilent(this._env)) { + return []; + } + return commentNode; + }, + + visitMedia: function(mediaNode, visitArgs) { + mediaNode.accept(this._visitor); + visitArgs.visitDeeper = false; + + if (!mediaNode.rules.length) { + return []; + } + return mediaNode; + }, + + visitDirective: function(directiveNode, visitArgs) { + if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) { + return []; + } + if (directiveNode.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (this.charset) { + if (directiveNode.debugInfo) { + var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n"); + comment.debugInfo = directiveNode.debugInfo; + return this._visitor.visit(comment); + } + return []; + } + this.charset = true; + } + return directiveNode; + }, + + checkPropertiesInRoot: function(rules) { + var ruleNode; + for(var i = 0; i < rules.length; i++) { + ruleNode = rules[i]; + if (ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null}; + } + } + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var rule, rulesets = []; + if (rulesetNode.firstRoot) { + this.checkPropertiesInRoot(rulesetNode.rules); + } + if (! rulesetNode.root) { + + rulesetNode.paths = rulesetNode.paths + .filter(function(p) { + var i; + if (p[0].elements[0].combinator.value === ' ') { + p[0].elements[0].combinator = new(tree.Combinator)(''); + } + for(i = 0; i < p.length; i++) { + if (p[i].getIsReferenced() && p[i].getIsOutput()) { + return true; + } + return false; + } + }); + + // Compile rules and rulesets + for (var i = 0; i < rulesetNode.rules.length; i++) { + rule = rulesetNode.rules[i]; + + if (rule.rules) { + // visit because we are moving them out from being a child + rulesets.push(this._visitor.visit(rule)); + rulesetNode.rules.splice(i, 1); + i--; + continue; + } + } + // accept the visitor to remove rules and refactor itself + // then we can decide now whether we want it or not + if (rulesetNode.rules.length > 0) { + rulesetNode.accept(this._visitor); + } + visitArgs.visitDeeper = false; + + this._mergeRules(rulesetNode.rules); + this._removeDuplicateRules(rulesetNode.rules); + + // now decide whether we keep the ruleset + if (rulesetNode.rules.length > 0 && rulesetNode.paths.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } else { + rulesetNode.accept(this._visitor); + visitArgs.visitDeeper = false; + if (rulesetNode.firstRoot || rulesetNode.rules.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } + if (rulesets.length === 1) { + return rulesets[0]; + } + return rulesets; + }, + + _removeDuplicateRules: function(rules) { + // remove duplicates + var ruleCache = {}, + ruleList, rule, i; + for(i = rules.length - 1; i >= 0 ; i--) { + rule = rules[i]; + if (rule instanceof tree.Rule) { + if (!ruleCache[rule.name]) { + ruleCache[rule.name] = rule; + } else { + ruleList = ruleCache[rule.name]; + if (ruleList instanceof tree.Rule) { + ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)]; + } + var ruleCSS = rule.toCSS(this._env); + if (ruleList.indexOf(ruleCSS) !== -1) { + rules.splice(i, 1); + } else { + ruleList.push(ruleCSS); + } + } + } + } + }, + + _mergeRules: function (rules) { + var groups = {}, + parts, + rule, + key; + + for (var i = 0; i < rules.length; i++) { + rule = rules[i]; + + if ((rule instanceof tree.Rule) && rule.merge) { + key = [rule.name, + rule.important ? "!" : ""].join(","); + + if (!groups[key]) { + parts = groups[key] = []; + } else { + rules.splice(i--, 1); + } + + parts.push(rule); + } + } + + Object.keys(groups).map(function (k) { + parts = groups[k]; + + if (parts.length > 1) { + rule = parts[0]; + + rule.value = new (tree.Value)(parts.map(function (p) { + return p.value; + })); + } + }); + } + }; + +})(require('./tree')); +(function (tree) { + /*jshint loopfunc:true */ + + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + rulesetNode.extendOnEveryPath = true; + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (rulesetNode.extendOnEveryPath || selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator === '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + elementValue1 = elementValue1.value; + elementValue2 = elementValue2.value; + if (elementValue1 instanceof tree.Selector) { + if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) { + return false; + } + for(var i = 0; i currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + newElements = selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)); + + if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) { + path[path.length - 1].elements = + path[path.length - 1].elements.concat(newElements); + } else { + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + newElements + )); + } + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.sourceMapOutput = function (options) { + this._css = []; + this._rootNode = options.rootNode; + this._writeSourceMap = options.writeSourceMap; + this._contentsMap = options.contentsMap; + this._sourceMapFilename = options.sourceMapFilename; + this._outputFilename = options.outputFilename; + this._sourceMapURL = options.sourceMapURL; + this._sourceMapBasepath = options.sourceMapBasepath; + this._sourceMapRootpath = options.sourceMapRootpath; + this._outputSourceFiles = options.outputSourceFiles; + this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator; + + if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') { + this._sourceMapRootpath += '/'; + } + + this._lineNumber = 0; + this._column = 0; + }; + + tree.sourceMapOutput.prototype.normalizeFilename = function(filename) { + if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { + filename = filename.substring(this._sourceMapBasepath.length); + if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { + filename = filename.substring(1); + } + } + return (this._sourceMapRootpath || "") + filename.replace(/\\/g, '/'); + }; + + tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { + + //ignore adding empty strings + if (!chunk) { + return; + } + + var lines, + sourceLines, + columns, + sourceColumns, + i; + + if (fileInfo) { + var inputSource = this._contentsMap[fileInfo.filename].substring(0, index); + sourceLines = inputSource.split("\n"); + sourceColumns = sourceLines[sourceLines.length-1]; + } + + lines = chunk.split("\n"); + columns = lines[lines.length-1]; + + if (fileInfo) { + if (!mapLines) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column}, + original: { line: sourceLines.length, column: sourceColumns.length}, + source: this.normalizeFilename(fileInfo.filename)}); + } else { + for(i = 0; i < lines.length; i++) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0}, + original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0}, + source: this.normalizeFilename(fileInfo.filename)}); + } + } + } + + if (lines.length === 1) { + this._column += columns.length; + } else { + this._lineNumber += lines.length - 1; + this._column = columns.length; + } + + this._css.push(chunk); + }; + + tree.sourceMapOutput.prototype.isEmpty = function() { + return this._css.length === 0; + }; + + tree.sourceMapOutput.prototype.toCSS = function(env) { + this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null }); + + if (this._outputSourceFiles) { + for(var filename in this._contentsMap) { + this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), this._contentsMap[filename]); + } + } + + this._rootNode.genCSS(env, this); + + if (this._css.length > 0) { + var sourceMapURL, + sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON()); + + if (this._sourceMapURL) { + sourceMapURL = this._sourceMapURL; + } else if (this._sourceMapFilename) { + sourceMapURL = this.normalizeFilename(this._sourceMapFilename); + } + + if (this._writeSourceMap) { + this._writeSourceMap(sourceMapContent); + } else { + sourceMapURL = "data:application/json," + encodeURIComponent(sourceMapContent); + } + + if (sourceMapURL) { + this._css.push("/*# sourceMappingURL=" + sourceMapURL + " */"); + } + } + + return this._css.join(''); + }; + +})(require('./tree')); + +// +// browser.js - client-side engine +// +/*global less, window, document, XMLHttpRequest, location */ + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + (location.port && + location.port.length > 0) || + isFileProtocol ? 'development' + : 'production'); + +var logLevel = { + info: 2, + errors: 1, + none: 0 +}; + +// The amount of logging in the javascript console. +// 2 - Information and errors +// 1 - Errors +// 0 - None +// Defaults to 2 +less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : logLevel.info; + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +var typePattern = /^text\/(x-)?less$/; +var cache = null; +var fileCache = {}; +var varsPre = ""; + +function log(str, level) { + if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) { + console.log('less: ' + str); + } +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function errorConsole(e, rootHref) { + var template = '{line} {content}'; + var filename = e.filename || rootHref; + var errors = []; + var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + " in " + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + errors.join('\n'); + } else if (e.stack) { + content += e.stack; + } + log(content, logLevel.errors); +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss === null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + if (nextEl) { + nextEl.parentNode.insertBefore(css, nextEl); + } else { + head.appendChild(css); + } + } + if (oldCss && keepOldCss === false) { + oldCss.parentNode.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.', logLevel.info); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save', logLevel.errors); + } + } +} + +function errorHTML(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, errors = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + errors.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +function error(e, rootHref) { + if (!less.errorReporting || less.errorReporting === "html") { + errorHTML(e, rootHref); + } else if (less.errorReporting === "console") { + errorConsole(e, rootHref); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("add", e, rootHref); + } +} + +function removeErrorHTML(path) { + var node = document.getElementById('less-error-message:' + extractId(path)); + if (node) { + node.parentNode.removeChild(node); + } +} + +function removeErrorConsole(path) { + //no action +} + +function removeError(path) { + if (!less.errorReporting || less.errorReporting === "html") { + removeErrorHTML(path); + } else if (less.errorReporting === "console") { + removeErrorConsole(path); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("remove", path); + } +} + +function loadStyles(newVars) { + var styles = document.getElementsByTagName('style'), + style; + for (var i = 0; i < styles.length; i++) { + style = styles[i]; + if (style.type.match(typePattern)) { + var env = new less.tree.parseEnv(less), + lessText = style.innerHTML || ''; + env.filename = document.location.href.replace(/#.*$/, ''); + + if (newVars || varsPre) { + env.useFileCache = true; + + lessText = varsPre + lessText; + + if (newVars) { + lessText += "\n" + newVars; + } + } + + /*jshint loopfunc:true */ + // use closure to store current value of i + var callback = (function(style) { + return function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }; + })(style); + new(less.Parser)(env).parse(lessText, callback); + } + } +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } else { + try { + /*global ActiveXObject */ + return new ActiveXObject("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX.", logLevel.errors); + return null; + } + } +} + +function doXHR(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + log("XHR: Getting '" + url + "'", logLevel.info); + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } +} + +function loadFile(originalHref, currentFileInfo, callback, env, newVars) { + + if (currentFileInfo && currentFileInfo.currentDirectory && !/^([a-z-]+:)?\//.test(originalHref)) { + originalHref = currentFileInfo.currentDirectory + originalHref; + } + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(originalHref, window.location.href); + var href = hrefParts.url; + var newFileInfo = { + currentDirectory: hrefParts.path, + filename: href + }; + + if (currentFileInfo) { + newFileInfo.entryPath = currentFileInfo.entryPath; + newFileInfo.rootpath = currentFileInfo.rootpath; + newFileInfo.rootFilename = currentFileInfo.rootFilename; + newFileInfo.relativeUrls = currentFileInfo.relativeUrls; + } else { + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + newFileInfo.relativeUrls = env.relativeUrls; + } + + if (newFileInfo.relativeUrls) { + if (env.rootpath) { + newFileInfo.rootpath = extractUrlParts(env.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + if (env.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + if (newVars) { + lessText += "\n" + newVars; + } + callback(null, lessText, href, newFileInfo, { lastModified: new Date() }); + } catch (e) { + callback(e, null, href); + } + return; + } + + doXHR(href, env.mime, function (data, lastModified) { + data = varsPre + data; + + // per file cache + fileCache[href] = data; + + // Use remote copy (re-parse) + try { + callback(null, data, href, newFileInfo, { lastModified: lastModified }); + } catch (e) { + callback(e, null, href); + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href); + }); +} + +function loadStyleSheet(sheet, callback, reload, remaining, newVars) { + + var env = new less.tree.parseEnv(less); + env.mime = sheet.type; + + if (newVars || varsPre) { + env.useFileCache = true; + } + + loadFile(sheet.href, null, function(e, data, path, newFileInfo, webInfo) { + + if (webInfo) { + webInfo.remaining = remaining; + + var css = cache && cache.getItem(path), + timestamp = cache && cache.getItem(path + ':timestamp'); + + if (!reload && timestamp && webInfo.lastModified && + (new(Date)(webInfo.lastModified).valueOf() === + new(Date)(timestamp).valueOf())) { + // Use local copy + createCSS(css, sheet); + webInfo.local = true; + callback(null, null, data, sheet, webInfo, path); + return; + } + } + + //TODO add tests around how this behaves when reloading + removeError(path); + + if (data) { + env.currentFileInfo = newFileInfo; + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, webInfo, path); + } catch (e) { + callback(e, null, null, sheet); + } + }); + } else { + callback(e, null, null, sheet, webInfo, path); + } + }, env, newVars); +} + +function loadStyleSheets(callback, reload, newVars) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), newVars); + } +} + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +function serializeVars(vars) { + var s = ""; + + for (var name in vars) { + s += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((vars[name].slice(-1) === ';')? vars[name] : vars[name] +';'); + } + + return s; +} + + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true; +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +less.modifyVars = function(record) { + less.refresh(false, serializeVars(record)); +}; + +less.refresh = function (reload, newVars) { + var startTime, endTime; + startTime = endTime = new Date(); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache.", logLevel.info); + } else { + log("parsed " + sheet.href + " successfully.", logLevel.info); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info); + if (env.remaining === 0) { + log("css generated in " + (new Date() - startTime) + 'ms', logLevel.info); + } + endTime = new Date(); + }, reload, newVars); + + loadStyles(newVars); +}; + +if (less.globalVars) { + varsPre = serializeVars(less.globalVars) + "\n"; +} + +less.refreshStyles = loadStyles; + +less.Parser.fileLoader = loadFile; + +less.refresh(less.env === 'development'); + +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} + +})(window); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.1.min.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.1.min.js new file mode 100644 index 000000000..535d9f56e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-1.5.1.min.js @@ -0,0 +1,13 @@ +/*! + * LESS - Leaner CSS v1.5.1 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache v2 License. + * + * @licence + */ + +!function(a,b){function c(b){return a.less[b.split("/")[1]]}function d(a,b){"development"==w.env&&"undefined"!=typeof console&&w.logLevel>=b&&console.log("less: "+a)}function e(a){return a.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function f(a,c){var e="{line} {content}",f=a.filename||c,g=[],h=(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+" in "+f+" ",i=function(a,c,d){a.extract[c]!==b&&g.push(e.replace(/\{line\}/,(parseInt(a.line,10)||0)+(c-1)).replace(/\{class\}/,d).replace(/\{content\}/,a.extract[c]))};a.extract?(i(a,0,""),i(a,1,"line"),i(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":\n"+g.join("\n")):a.stack&&(h+=a.stack),d(h,z.errors)}function g(a,b,c){var f=b.href||"",g="less:"+(b.title||e(f)),h=document.getElementById(g),i=!1,j=document.createElement("style");if(j.setAttribute("type","text/css"),b.media&&j.setAttribute("media",b.media),j.id=g,j.styleSheet)try{j.styleSheet.cssText=a}catch(k){throw new Error("Couldn't reassign styleSheet.cssText.")}else j.appendChild(document.createTextNode(a)),i=null!==h&&h.childNodes.length>0&&j.childNodes.length>0&&h.firstChild.nodeValue===j.firstChild.nodeValue;var l=document.getElementsByTagName("head")[0];if(null===h||i===!1){var m=b&&b.nextSibling||null;m?m.parentNode.insertBefore(j,m):l.appendChild(j)}if(h&&i===!1&&h.parentNode.removeChild(h),c&&D){d("saving "+f+" to cache.",z.info);try{D.setItem(f,a),D.setItem(f+":timestamp",c)}catch(k){d("failed to save",z.errors)}}}function h(a,c){var d,f,h="less-error-message:"+e(c||""),i='
  • {content}
  • ',j=document.createElement("div"),k=[],l=a.filename||c,m=l.match(/([^\/]+(\?.*)?)$/)[1];j.id=h,j.className="less-error-message",f="

    "+(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+'

    in '+m+" ";var n=function(a,c,d){a.extract[c]!==b&&k.push(i.replace(/\{line\}/,(parseInt(a.line,10)||0)+(c-1)).replace(/\{class\}/,d).replace(/\{content\}/,a.extract[c]))};a.extract?(n(a,0,""),n(a,1,"line"),n(a,2,""),f+="on line "+a.line+", column "+(a.column+1)+":

      "+k.join("")+"
    "):a.stack&&(f+="
    "+a.stack.split("\n").slice(1).join("
    ")),j.innerHTML=f,g([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),j.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),"development"==w.env&&(d=setInterval(function(){document.body&&(document.getElementById(h)?document.body.replaceChild(j,document.getElementById(h)):document.body.insertBefore(j,document.body.firstChild),clearInterval(d))},10))}function i(a,b){w.errorReporting&&"html"!==w.errorReporting?"console"===w.errorReporting?f(a,b):"function"==typeof w.errorReporting&&w.errorReporting("add",a,b):h(a,b)}function j(a){var b=document.getElementById("less-error-message:"+e(a));b&&b.parentNode.removeChild(b)}function k(){}function l(a){w.errorReporting&&"html"!==w.errorReporting?"console"===w.errorReporting?k(a):"function"==typeof w.errorReporting&&w.errorReporting("remove",a):j(a)}function m(a){for(var b,c=document.getElementsByTagName("style"),d=0;d0&&(h.splice(c-1,2),c-=2)}return g.hostPart=f[1],g.directories=h,g.path=f[1]+h.join("/"),g.fileUrl=g.path+(f[4]||""),g.url=g.fileUrl+(f[5]||""),g}function o(a,b){var c,d,e,f,g=n(a),h=n(b),i="";if(g.hostPart!==h.hostPart)return"";for(d=Math.max(h.directories.length,g.directories.length),c=0;d>c&&h.directories[c]===g.directories[c];c++);for(f=h.directories.slice(c),e=g.directories.slice(c),c=0;c=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):"function"==typeof d&&d(b.status,a)}var g=p(),h=y?w.fileAsync:w.async;"function"==typeof g.overrideMimeType&&g.overrideMimeType("text/css"),d("XHR: Getting '"+a+"'",z.info),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),y&&!w.fileAsync?0===g.status||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){4==g.readyState&&f(g,c,e)}:f(g,c,e)}function r(b,c,d,e,f){c&&c.currentDirectory&&!/^([a-z-]+:)?\//.test(b)&&(b=c.currentDirectory+b);var g=n(b,a.location.href),h=g.url,i={currentDirectory:g.path,filename:h};if(c?(i.entryPath=c.entryPath,i.rootpath=c.rootpath,i.rootFilename=c.rootFilename,i.relativeUrls=c.relativeUrls):(i.entryPath=g.path,i.rootpath=w.rootpath||g.path,i.rootFilename=h,i.relativeUrls=e.relativeUrls),i.relativeUrls&&(i.rootpath=e.rootpath?n(e.rootpath+o(g.path,i.entryPath)).path:g.path),e.useFileCache&&E[h])try{var j=E[h];f&&(j+="\n"+f),d(null,j,h,i,{lastModified:new Date})}catch(k){d(k,null,h)}else q(h,e.mime,function(a,b){a=F+a,E[h]=a;try{d(null,a,h,i,{lastModified:b})}catch(c){d(c,null,h)}},function(a,b){d({type:"File",message:"'"+b+"' wasn't found ("+a+")"},null,h)})}function s(a,b,c,d,e){var f=new w.tree.parseEnv(w);f.mime=a.type,(e||F)&&(f.useFileCache=!0),r(a.href,null,function(e,h,i,j,k){if(k){k.remaining=d;var m=D&&D.getItem(i),n=D&&D.getItem(i+":timestamp");if(!c&&n&&k.lastModified&&new Date(k.lastModified).valueOf()===new Date(n).valueOf())return g(m,a),k.local=!0,b(null,null,h,a,k,i),void 0}l(i),h?(f.currentFileInfo=j,new w.Parser(f).parse(h,function(c,d){if(c)return b(c,null,null,a);try{b(c,d,h,a,k,i)}catch(c){b(c,null,null,a)}})):b(e,null,null,a,k,i)},f,e)}function t(a,b,c){for(var d=0;dz&&(y[s]=y[s].slice(r-z),z=r)}function g(a){var b=a.charCodeAt(0);return 32===b||10===b||9===b}function h(a){var b,c;if(a instanceof Function)return a.call(A.parsers);if("string"==typeof a)b=q.charAt(r)===a?a:null,c=1,f();else{if(f(),!(b=a.exec(y[s])))return null;c=b[0].length}return b?(i(c),"string"==typeof b?b:1===b.length?b[0]:b):void 0}function i(a){for(var b=r,c=s,d=r+y[s].length,e=r+=a;d>r&&g(q.charAt(r));)r++;return y[s]=y[s].slice(a+(r-e)),z=r,0===y[s].length&&s=0&&"\n"!==b.charAt(c);)e++;return"number"==typeof a&&(d=(b.slice(0,a).match(/\n/g)||"").length),{line:d,column:e}}function o(a,b,d){var e=d.currentFileInfo.filename;return"browser"!==w.mode&&"rhino"!==w.mode&&(e=c("path").resolve(e)),{lineNumber:n(a,b).line+1,fileName:e}}function p(a,b){var c=m(a,b),d=n(a.index,c),e=d.line,f=d.column,g=a.call&&n(a.call,c).line,h=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.currentFileInfo.filename,this.index=a.index,this.line="number"==typeof e?e+1:null,this.callLine=g+1,this.callExtract=h[g],this.stack=a.stack,this.column=f,this.extract=[h[e-1],h[e],h[e+1]]}var q,r,s,t,u,v,y,z,A,B=a&&a.filename;a instanceof x.parseEnv||(a=new x.parseEnv(a));var C=this.imports={paths:a.paths||[],queue:[],files:a.files,contents:a.contents,mime:a.mime,error:null,push:function(b,c,d,e){var f=this;this.queue.push(b);var g=function(a,c,d){f.queue.splice(f.queue.indexOf(b),1);var g=d in f.files||d===B;f.files[d]=c,a&&!f.error&&(f.error=a),e(a,c,g,d)};w.Parser.importer?w.Parser.importer(b,c,g,a):w.Parser.fileLoader(b,c,function(b,e,f,h){if(b)return g(b),void 0;var i=new x.parseEnv(a);i.currentFileInfo=h,i.processImports=!1,i.contents[f]=e,(c.reference||d.reference)&&(h.reference=!0),d.inline?g(null,e,f):new w.Parser(i).parse(e,function(a,b){g(a,b,f)})},a)}};return p.prototype=new Error,p.prototype.constructor=p,this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,A={imports:C,parse:function(b,d){var e,f,g,i=null;if(r=s=z=v=0,q=b.replace(/\r\n/g,"\n"),q=q.replace(/^\uFEFF/,""),A.imports.contents[a.currentFileInfo.filename]=q,y=function(b){for(var c,d,e,f,g=0,h=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,j=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,k=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,l=0,m=b[0],n=0;n0?"missing closing `}`":"missing opening `{`",filename:a.currentFileInfo.filename},a)),b.map(function(a){return a.join("")})}([[]]),i)return d(new p(i,a));try{e=new x.Ruleset([],h(this.parsers.primary)),e.root=!0,e.firstRoot=!0}catch(j){return d(new p(j,a))}if(e.toCSS=function(b){return function(d,e){d=d||{};var f,g,h=new x.evalEnv(d);"object"!=typeof e||Array.isArray(e)||(e=Object.keys(e).map(function(a){var b=e[a];return b instanceof x.Value||(b instanceof x.Expression||(b=new x.Expression([b])),b=new x.Value([b])),new x.Rule("@"+a,b,!1,null,0)}),h.frames=[new x.Ruleset(null,e)]);try{f=b.call(this,h),(new x.joinSelectorVisitor).run(f),(new x.processExtendsVisitor).run(f),new x.toCSSVisitor({compress:Boolean(d.compress)}).run(f),d.sourceMap&&(f=new x.sourceMapOutput({writeSourceMap:d.writeSourceMap,rootNode:f,contentsMap:A.imports.contents,sourceMapFilename:d.sourceMapFilename,sourceMapURL:d.sourceMapURL,outputFilename:d.sourceMapOutputFilename,sourceMapBasepath:d.sourceMapBasepath,sourceMapRootpath:d.sourceMapRootpath,outputSourceFiles:d.outputSourceFiles,sourceMapGenerator:d.sourceMapGenerator})),g=f.toCSS({compress:Boolean(d.compress),dumpLineNumbers:a.dumpLineNumbers,strictUnits:Boolean(d.strictUnits)})}catch(i){throw new p(i,a)}if(d.cleancss&&"node"===w.mode){var j=c("clean-css");return new j({keepSpecialComments:"*",processImport:!1,noRebase:!0,noAdvanced:!0}).minify(g)}return d.compress?g.replace(/(^(\s)+)|((\s)+$)/g,""):g}}(e.eval),r57||43>b||47===b||44==b))return(a=h(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))?new x.Dimension(a[1],a[2]):void 0},unicodeDescriptor:function(){var a;return(a=h(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))?new x.UnicodeDescriptor(a[0]):void 0},javascript:function(){var c,d,e=r;return"~"===q.charAt(e)&&(e++,d=!0),"`"===q.charAt(e)?(a.javascriptEnabled===b||a.javascriptEnabled||k("You are using JavaScript, which has been disabled."),d&&h("~"),(c=h(/^`([^`]*)`/))?new x.JavaScript(c[1],r,d):void 0):void 0}},variable:function(){var a;return"@"===q.charAt(r)&&(a=h(/^(@[\w-]+)\s*:/))?a[1]:void 0},extend:function(a){var b,c,d,e=r,f=[];if(h(a?/^&:extend\(/:/^:extend\(/)){do{for(d=null,b=[];;){if(d=h(/^(all)(?=\s*(\)|,))/))break;if(c=h(this.element),!c)break;b.push(c)}d=d&&d[1],f.push(new x.Extend(new x.Selector(b),d,e))}while(h(","));return j(/^\)/),a&&j(/^;/),f}},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var b,c,f,g=[],i=r,k=q.charAt(r),m=!1;if("."===k||"#"===k){for(d();b=h(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/);)g.push(new x.Element(c,b,r,a.currentFileInfo)),c=h(">");return h("(")&&(f=this.mixin.args.call(this,!0).args,j(")")),f=f||[],h(this.important)&&(m=!0),g.length>0&&(h(";")||l("}"))?new x.mixin.Call(g,f,i,a.currentFileInfo,m):(e(),void 0)}},args:function(a){for(var b,c,d,e,f,g,i=[],l=[],m=[],n={args:null,variadic:!1};;){if(a)g=h(this.expression);else{if(h(this.comments),"."===q.charAt(r)&&h(/^\.{3}/)){n.variadic=!0,h(";")&&!b&&(b=!0),(b?l:m).push({variadic:!0});break}g=h(this.entities.variable)||h(this.entities.literal)||h(this.entities.keyword)}if(!g)break;e=null,g.throwAwayComments&&g.throwAwayComments(),f=g;var o=null;if(a?1==g.value.length&&(o=g.value[0]):o=g,o&&o instanceof x.Variable)if(h(":"))i.length>0&&(b&&k("Cannot mix ; and , as delimiter types"),c=!0),f=j(this.expression),e=d=o.name;else{if(!a&&h(/^\.{3}/)){n.variadic=!0,h(";")&&!b&&(b=!0),(b?l:m).push({name:g.name,variadic:!0});break}a||(d=e=o.name,f=null)}f&&i.push(f),m.push({name:e,value:f}),h(",")||(h(";")||b)&&(c&&k("Cannot mix ; and , as delimiter types"),b=!0,i.length>1&&(f=new x.Value(i)),l.push({name:d,value:f}),d=null,i=[],c=!1)}return n.args=b?l:m,n},definition:function(){var a,b,c,f,g=[],i=!1;if(!("."!==q.charAt(r)&&"#"!==q.charAt(r)||l(/^[^{]*\}/))&&(d(),b=h(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/))){a=b[1];var k=this.mixin.args.call(this,!1);if(g=k.args,i=k.variadic,h(")")||(v=r,e()),h(this.comments),h(/^when/)&&(f=j(this.conditions,"expected condition")),c=h(this.block))return new x.mixin.Definition(a,g,c,f,i);e()}}},entity:function(){return h(this.entities.literal)||h(this.entities.variable)||h(this.entities.url)||h(this.entities.call)||h(this.entities.keyword)||h(this.entities.javascript)||h(this.comment)},end:function(){return h(";")||l("}")},alpha:function(){var a;if(h(/^\(opacity=/i))return(a=h(/^\d+/)||h(this.entities.variable))?(j(")"),new x.Alpha(a)):void 0},element:function(){var b,c,d;return c=h(this.combinator),b=h(/^(?:\d+\.\d+|\d+)%/)||h(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||h("*")||h("&")||h(this.attribute)||h(/^\([^()@]+\)/)||h(/^[\.#](?=@)/)||h(this.entities.variableCurly),b||h("(")&&(d=h(this.selector))&&h(")")&&(b=new x.Paren(d)),b?new x.Element(c,b,r,a.currentFileInfo):void 0},combinator:function(){var a=q.charAt(r);if(">"===a||"+"===a||"~"===a||"|"===a){for(r++;q.charAt(r).match(/\s/);)r++;return new x.Combinator(a)}return q.charAt(r-1).match(/\s/)?new x.Combinator(" "):new x.Combinator(null)},lessSelector:function(){return this.selector(!0)},selector:function(b){for(var c,d,e,f,g,i=[],l=[];(b&&(e=h(this.extend))||b&&(f=h(/^when/))||(c=h(this.element)))&&(f?g=j(this.conditions,"expected condition"):g?k("CSS guard can only be used at the end of selector"):e?l.push.apply(l,e):(l.length&&k("Extend can only be used at the end of selector"),d=q.charAt(r),i.push(c),c=null),"{"!==d&&"}"!==d&&";"!==d&&","!==d&&")"!==d););return i.length>0?new x.Selector(i,l,g,r,a.currentFileInfo):(l.length&&k("Extend must be used to extend a selector, it cannot be used on its own"),void 0)},attribute:function(){var a,b,c;if(h("["))return(a=h(this.entities.variableCurly))||(a=j(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/)),(c=h(/^[|~*$^]?=/))&&(b=h(this.entities.quoted)||h(/^[0-9]+%/)||h(/^[\w-]+/)||h(this.entities.variableCurly)),j("]"),new x.Attribute(a,c,b)},block:function(){var a;return h("{")&&(a=h(this.primary))&&h("}")?a:void 0},ruleset:function(){var b,c,f,g=[];for(d(),a.dumpLineNumbers&&(f=o(r,q,a));(b=h(this.lessSelector))&&(g.push(b),h(this.comments),h(","));)b.condition&&k("Guards are only currently allowed on a single selector."),h(this.comments);if(g.length>0&&(c=h(this.block))){var i=new x.Ruleset(g,c,a.strictImports);return a.dumpLineNumbers&&(i.debugInfo=f),i}v=r,e()},rule:function(b){var c,f,g,i=q.charAt(r),j=!1;if(d(),"."!==i&&"#"!==i&&"&"!==i&&(c=h(this.variable)||h(this.ruleProperty))){if(f=b||!a.compress&&"@"!==c.charAt(0)?h(this.anonymousValue)||h(this.value):h(this.value)||h(this.anonymousValue),g=h(this.important),"+"===c[c.length-1]&&(j=!0,c=c.substr(0,c.length-1)),f&&h(this.end))return new x.Rule(c,f,g,j,u,a.currentFileInfo);if(v=r,e(),f&&!b)return this.rule(!0)}},anonymousValue:function(){var a;return(a=/^([^@+\/'"*`(;{}-]*);/.exec(y[s]))?(r+=a[0].length-1,new x.Anonymous(a[1])):void 0},"import":function(){var b,c,f=r;d();var g=h(/^@import?\s+/),i=(g?h(this.importOptions):null)||{};return g&&(b=h(this.entities.quoted)||h(this.entities.url))&&(c=h(this.mediaFeatures),h(";"))?(c=c&&new x.Value(c),new x.Import(b,c,i,f,a.currentFileInfo)):(e(),void 0)},importOptions:function(){var a,b,c,d={};if(!h("("))return null;do if(a=h(this.importOption)){switch(b=a,c=!0,b){case"css":b="less",c=!1;break;case"once":b="multiple",c=!1}if(d[b]=c,!h(","))break}while(a);return j(")"),d},importOption:function(){var a=h(/^(less|css|multiple|once|inline|reference)/);return a?a[1]:void 0},mediaFeature:function(){var b,c,d=[];do if(b=h(this.entities.keyword)||h(this.entities.variable))d.push(b);else if(h("(")){if(c=h(this.property),b=h(this.value),!h(")"))return null;if(c&&b)d.push(new x.Paren(new x.Rule(c,b,null,null,r,a.currentFileInfo,!0)));else{if(!b)return null;d.push(new x.Paren(b))}}while(b);return d.length>0?new x.Expression(d):void 0},mediaFeatures:function(){var a,b=[];do if(a=h(this.mediaFeature)){if(b.push(a),!h(","))break}else if((a=h(this.entities.variable))&&(b.push(a),!h(",")))break;while(a);return b.length>0?b:null},media:function(){var b,c,d,e;return a.dumpLineNumbers&&(e=o(r,q,a)),h(/^@media/)&&(b=h(this.mediaFeatures),c=h(this.block))?(d=new x.Media(c,b,r,a.currentFileInfo),a.dumpLineNumbers&&(d.debugInfo=e),d):void 0},directive:function(){var b,c,f,g,i,j,k,l;if("@"===q.charAt(r)){if(c=h(this["import"])||h(this.media))return c;if(d(),b=h(/^@[a-z-]+/)){switch(g=b,"-"==b.charAt(1)&&b.indexOf("-",2)>0&&(g="@"+b.slice(b.indexOf("-",2)+1)),g){case"@font-face":i=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":i=!0;break;case"@host":case"@page":case"@document":case"@supports":case"@keyframes":i=!0,j=!0;break;case"@namespace":k=!0}if(j&&(l=(h(/^[^{]+/)||"").trim(),l&&(b+=" "+l)),i){if(f=h(this.block))return new x.Directive(b,f,r,a.currentFileInfo)}else if((c=k?h(this.expression):h(this.entity))&&h(";")){var m=new x.Directive(b,c,r,a.currentFileInfo);return a.dumpLineNumbers&&(m.debugInfo=o(r,q,a)),m}e()}}},value:function(){for(var a,b=[];(a=h(this.expression))&&(b.push(a),h(",")););return b.length>0?new x.Value(b):void 0},important:function(){return"!"===q.charAt(r)?h(/^! *important/):void 0},sub:function(){var a,b;return h("(")&&(a=h(this.addition))?(b=new x.Expression([a]),j(")"),b.parens=!0,b):void 0},multiplication:function(){var a,b,c,d,e;if(a=h(this.operand)){for(e=g(q.charAt(r-1));!l(/^\/[*\/]/)&&(c=h("/")||h("*"))&&(b=h(this.operand));)a.parensInOp=!0,b.parensInOp=!0,d=new x.Operation(c,[d||a,b],e),e=g(q.charAt(r-1));return d||a}},addition:function(){var a,b,c,d,e;if(a=h(this.multiplication)){for(e=g(q.charAt(r-1));(c=h(/^[-+]\s+/)||!e&&(h("+")||h("-")))&&(b=h(this.multiplication));)a.parensInOp=!0,b.parensInOp=!0,d=new x.Operation(c,[d||a,b],e),e=g(q.charAt(r-1));return d||a}},conditions:function(){var a,b,c,d=r;if(a=h(this.condition)){for(;l(/^,\s*(not\s*)?\(/)&&h(",")&&(b=h(this.condition));)c=new x.Condition("or",c||a,b,d);return c||a}},condition:function(){var a,b,c,d,e=r,f=!1;return h(/^not/)&&(f=!0),j("("),(a=h(this.addition)||h(this.entities.keyword)||h(this.entities.quoted))?((d=h(/^(?:>=|<=|=<|[<=>])/))?(b=h(this.addition)||h(this.entities.keyword)||h(this.entities.quoted))?c=new x.Condition(d,a,b,e,f):k("expected expression"):c=new x.Condition("=",a,new x.Keyword("true"),e,f),j(")"),h(/^and/)?new x.Condition("and",c,h(this.condition)):c):void 0},operand:function(){var a,b=q.charAt(r+1);"-"!==q.charAt(r)||"@"!==b&&"("!==b||(a=h("-"));var c=h(this.sub)||h(this.entities.dimension)||h(this.entities.color)||h(this.entities.variable)||h(this.entities.call);return a&&(c.parensInOp=!0,c=new x.Negative(c)),c},expression:function(){for(var a,b,c=[];a=h(this.addition)||h(this.entity);)c.push(a),!l(/^\/[\/*]/)&&(b=h("/"))&&c.push(new x.Anonymous(b));return c.length>0?new x.Expression(c):void 0},property:function(){var a;return(a=h(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/))?a[1]:void 0},ruleProperty:function(){var a;return(a=h(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/))?a[1]+(a[2]||""):void 0}}}},function(d){function e(a){return d.functions.hsla(a.h,a.s,a.l,a.a)}function f(a,b){return a instanceof d.Dimension&&a.unit.is("%")?parseFloat(a.value*b/100):g(a)}function g(a){if(a instanceof d.Dimension)return parseFloat(a.unit.is("%")?a.value/100:a.value);if("number"==typeof a)return a;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function h(a){return Math.min(1,Math.max(0,a))}d.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(a,b,c,e){var h=[a,b,c].map(function(a){return f(a,256)});return e=g(e),new d.Color(h,e)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,c,d){function e(a){return a=0>a?a+1:a>1?a-1:a,1>6*a?i+(f-i)*a*6:1>2*a?f:2>3*a?i+(f-i)*(2/3-a)*6:i}a=g(a)%360/360,b=h(g(b)),c=h(g(c)),d=h(g(d));var f=.5>=c?c*(b+1):c+b-c*b,i=2*c-f;return this.rgba(255*e(a+1/3),255*e(a),255*e(a-1/3),d)},hsv:function(a,b,c){return this.hsva(a,b,c,1)},hsva:function(a,b,c,d){a=g(a)%360/360*360,b=g(b),c=g(c),d=g(d);var e,f;e=Math.floor(a/60%6),f=a/60-e;var h=[c,c*(1-b),c*(1-f*b),c*(1-(1-f)*b)],i=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(255*h[i[e][0]],255*h[i[e][1]],255*h[i[e][2]],d)},hue:function(a){return new d.Dimension(Math.round(a.toHSL().h))},saturation:function(a){return new d.Dimension(Math.round(100*a.toHSL().s),"%")},lightness:function(a){return new d.Dimension(Math.round(100*a.toHSL().l),"%")},hsvhue:function(a){return new d.Dimension(Math.round(a.toHSV().h))},hsvsaturation:function(a){return new d.Dimension(Math.round(100*a.toHSV().s),"%")},hsvvalue:function(a){return new d.Dimension(Math.round(100*a.toHSV().v),"%")},red:function(a){return new d.Dimension(a.rgb[0])},green:function(a){return new d.Dimension(a.rgb[1])},blue:function(a){return new d.Dimension(a.rgb[2])},alpha:function(a){return new d.Dimension(a.toHSL().a)},luma:function(a){return new d.Dimension(Math.round(a.luma()*a.alpha*100),"%")},saturate:function(a,b){if(!a.rgb)return null;var c=a.toHSL();return c.s+=b.value/100,c.s=h(c.s),e(c)},desaturate:function(a,b){var c=a.toHSL();return c.s-=b.value/100,c.s=h(c.s),e(c)},lighten:function(a,b){var c=a.toHSL();return c.l+=b.value/100,c.l=h(c.l),e(c)},darken:function(a,b){var c=a.toHSL();return c.l-=b.value/100,c.l=h(c.l),e(c)},fadein:function(a,b){var c=a.toHSL();return c.a+=b.value/100,c.a=h(c.a),e(c)},fadeout:function(a,b){var c=a.toHSL();return c.a-=b.value/100,c.a=h(c.a),e(c)},fade:function(a,b){var c=a.toHSL();return c.a=b.value/100,c.a=h(c.a),e(c)},spin:function(a,b){var c=a.toHSL(),d=(c.h+b.value)%360;return c.h=0>d?360+d:d,e(c)},mix:function(a,b,c){c||(c=new d.Dimension(50));var e=c.value/100,f=2*e-1,g=a.toHSL().a-b.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[a.rgb[0]*h+b.rgb[0]*i,a.rgb[1]*h+b.rgb[1]*i,a.rgb[2]*h+b.rgb[2]*i],k=a.alpha*e+b.alpha*(1-e);return new d.Color(j,k)},greyscale:function(a){return this.desaturate(a,new d.Dimension(100))},contrast:function(a,b,c,d){if(!a.rgb)return null;if("undefined"==typeof c&&(c=this.rgba(255,255,255,1)),"undefined"==typeof b&&(b=this.rgba(0,0,0,1)),b.luma()>c.luma()){var e=c;c=b,b=e}return d="undefined"==typeof d?.43:g(d),a.luma()*a.alphai.value)&&(k[f]=g)):(l[j]=k.length,k.push(g))):k.push(g);return 1==k.length?k[0]:(c=k.map(function(a){return a.toCSS(this.env)}).join(this.env.compress?",":", "),new d.Anonymous((a?"min":"max")+"("+c+")"))},min:function(){return this._minmax(!0,arguments)},max:function(){return this._minmax(!1,arguments)},argb:function(a){return new d.Anonymous(a.toARGB())},percentage:function(a){return new d.Dimension(100*a.value,"%")},color:function(a){if(a instanceof d.Quoted){var b,c=a.value;if(b=d.Color.fromKeyword(c))return b;if(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(c))return new d.Color(c.slice(1));throw{type:"Argument",message:"argument must be a color keyword or 3/6 digit hex e.g. #FFF"}}throw{type:"Argument",message:"argument must be a string"}},iscolor:function(a){return this._isa(a,d.Color)},isnumber:function(a){return this._isa(a,d.Dimension)},isstring:function(a){return this._isa(a,d.Quoted)},iskeyword:function(a){return this._isa(a,d.Keyword)},isurl:function(a){return this._isa(a,d.URL)},ispixel:function(a){return this.isunit(a,"px")},ispercentage:function(a){return this.isunit(a,"%")},isem:function(a){return this.isunit(a,"em")},isunit:function(a,b){return a instanceof d.Dimension&&a.unit.is(b.value||b)?d.True:d.False},_isa:function(a,b){return a instanceof b?d.True:d.False},multiply:function(a,b){var c=a.rgb[0]*b.rgb[0]/255,d=a.rgb[1]*b.rgb[1]/255,e=a.rgb[2]*b.rgb[2]/255;return this.rgb(c,d,e)},screen:function(a,b){var c=255-(255-a.rgb[0])*(255-b.rgb[0])/255,d=255-(255-a.rgb[1])*(255-b.rgb[1])/255,e=255-(255-a.rgb[2])*(255-b.rgb[2])/255;return this.rgb(c,d,e)},overlay:function(a,b){var c=a.rgb[0]<128?2*a.rgb[0]*b.rgb[0]/255:255-2*(255-a.rgb[0])*(255-b.rgb[0])/255,d=a.rgb[1]<128?2*a.rgb[1]*b.rgb[1]/255:255-2*(255-a.rgb[1])*(255-b.rgb[1])/255,e=a.rgb[2]<128?2*a.rgb[2]*b.rgb[2]/255:255-2*(255-a.rgb[2])*(255-b.rgb[2])/255; +return this.rgb(c,d,e)},softlight:function(a,b){var c=b.rgb[0]*a.rgb[0]/255,d=c+a.rgb[0]*(255-(255-a.rgb[0])*(255-b.rgb[0])/255-c)/255;c=b.rgb[1]*a.rgb[1]/255;var e=c+a.rgb[1]*(255-(255-a.rgb[1])*(255-b.rgb[1])/255-c)/255;c=b.rgb[2]*a.rgb[2]/255;var f=c+a.rgb[2]*(255-(255-a.rgb[2])*(255-b.rgb[2])/255-c)/255;return this.rgb(d,e,f)},hardlight:function(a,b){var c=b.rgb[0]<128?2*b.rgb[0]*a.rgb[0]/255:255-2*(255-b.rgb[0])*(255-a.rgb[0])/255,d=b.rgb[1]<128?2*b.rgb[1]*a.rgb[1]/255:255-2*(255-b.rgb[1])*(255-a.rgb[1])/255,e=b.rgb[2]<128?2*b.rgb[2]*a.rgb[2]/255:255-2*(255-b.rgb[2])*(255-a.rgb[2])/255;return this.rgb(c,d,e)},difference:function(a,b){var c=Math.abs(a.rgb[0]-b.rgb[0]),d=Math.abs(a.rgb[1]-b.rgb[1]),e=Math.abs(a.rgb[2]-b.rgb[2]);return this.rgb(c,d,e)},exclusion:function(a,b){var c=a.rgb[0]+b.rgb[0]*(255-a.rgb[0]-a.rgb[0])/255,d=a.rgb[1]+b.rgb[1]*(255-a.rgb[1]-a.rgb[1])/255,e=a.rgb[2]+b.rgb[2]*(255-a.rgb[2]-a.rgb[2])/255;return this.rgb(c,d,e)},average:function(a,b){var c=(a.rgb[0]+b.rgb[0])/2,d=(a.rgb[1]+b.rgb[1])/2,e=(a.rgb[2]+b.rgb[2])/2;return this.rgb(c,d,e)},negation:function(a,b){var c=255-Math.abs(255-b.rgb[0]-a.rgb[0]),d=255-Math.abs(255-b.rgb[1]-a.rgb[1]),e=255-Math.abs(255-b.rgb[2]-a.rgb[2]);return this.rgb(c,d,e)},tint:function(a,b){return this.mix(this.rgb(255,255,255),a,b)},shade:function(a,b){return this.mix(this.rgb(0,0,0),a,b)},extract:function(a,b){return b=b.value-1,Array.isArray(a.value)?a.value[b]:Array(a)[b]},length:function(a){var b=Array.isArray(a.value)?a.value.length:1;return new d.Dimension(b)},"data-uri":function(b,e){if("undefined"!=typeof a)return new d.URL(e||b,this.currentFileInfo).eval(this.env);var f=b.value,g=e&&e.value,h=c("fs"),i=c("path"),j=!1;if(arguments.length<2&&(g=f),this.env.isPathRelative(g)&&(g=this.currentFileInfo.relativeUrls?i.join(this.currentFileInfo.currentDirectory,g):i.join(this.currentFileInfo.entryPath,g)),arguments.length<2){var k;try{k=c("mime")}catch(l){k=d._mime}f=k.lookup(g);var m=k.charsets.lookup(f);j=["US-ASCII","UTF-8"].indexOf(m)<0,j&&(f+=";base64")}else j=/;base64$/.test(f);var n=h.readFileSync(g),o=32,p=parseInt(n.length/1024,10);if(p>=o&&this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",g,p,o),new d.URL(e||b,this.currentFileInfo).eval(this.env);n=j?n.toString("base64"):encodeURIComponent(n);var q="'data:"+f+","+n+"'";return new d.URL(new d.Anonymous(q))},"svg-gradient":function(a){function c(){throw{type:"Argument",message:"svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]"}}arguments.length<3&&c();var e,f,g,h,i,j,k,l=Array.prototype.slice.call(arguments,1),m="linear",n='x="0" y="0" width="1" height="1"',o=!0,p={compress:!1},q=a.toCSS(p);switch(q){case"to bottom":e='x1="0%" y1="0%" x2="0%" y2="100%"';break;case"to right":e='x1="0%" y1="0%" x2="100%" y2="0%"';break;case"to bottom right":e='x1="0%" y1="0%" x2="100%" y2="100%"';break;case"to top right":e='x1="0%" y1="100%" x2="100%" y2="0%"';break;case"ellipse":case"ellipse at center":m="radial",e='cx="50%" cy="50%" r="75%"',n='x="-50" y="-50" width="101" height="101"';break;default:throw{type:"Argument",message:"svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'"}}for(f='<'+m+'Gradient id="gradient" gradientUnits="userSpaceOnUse" '+e+">",g=0;gk?' stop-opacity="'+k+'"':"")+"/>";if(f+="',o)try{f=new Buffer(f).toString("base64")}catch(r){o=!1}return f="'data:image/svg+xml"+(o?";base64":"")+","+f+"'",new d.URL(new d.Anonymous(f))}},d._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(a){var e=c("path").extname(a),f=d._mime._types[e];if(f===b)throw new Error('Optional dependency "mime" is required for '+e);return f},charsets:{lookup:function(a){return a&&/^text\//.test(a)?"UTF-8":""}}};for(var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],j=function(a,b){return function(c){return null!=b&&(c=c.unify()),this._math(Math[a],b,c)}},k=0;k1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)},a.toCSS=function(a){var b=[];return this.genCSS(a,{add:function(a){b.push(a)},isEmpty:function(){return 0===b.length}}),b.join("")},a.outputRuleset=function(a,b,c){b.add(a.compress?"{":" {\n"),a.tabLevel=(a.tabLevel||0)+1;for(var d=a.compress?"":Array(a.tabLevel+1).join(" "),e=a.compress?"":Array(a.tabLevel).join(" "),f=0;fb?-1:1},genCSS:function(a,b){b.add(this.value,this.currentFileInfo,this.index,this.mapLines)},toCSS:a.toCSS}}(c("../tree")),function(a){a.Assignment=function(a,b){this.key=a,this.value=b},a.Assignment.prototype={type:"Assignment",accept:function(a){this.value=a.visit(this.value)},eval:function(b){return this.value.eval?new a.Assignment(this.key,this.value.eval(b)):this},genCSS:function(a,b){b.add(this.key+"="),this.value.genCSS?this.value.genCSS(a,b):b.add(this.value)},toCSS:a.toCSS}}(c("../tree")),function(a){a.Call=function(a,b,c,d){this.name=a,this.args=b,this.index=c,this.currentFileInfo=d},a.Call.prototype={type:"Call",accept:function(a){this.args=a.visit(this.args)},eval:function(b){var c,d,e=this.args.map(function(a){return a.eval(b)}),f=this.name.toLowerCase();if(f in a.functions)try{if(d=new a.functionCall(b,this.currentFileInfo),c=d[f].apply(d,e),null!=c)return c}catch(g){throw{type:g.type||"Runtime",message:"error evaluating function `"+this.name+"`"+(g.message?": "+g.message:""),index:this.index,filename:this.currentFileInfo.filename}}return new a.Call(this.name,e,this.index,this.currentFileInfo)},genCSS:function(a,b){b.add(this.name+"(",this.currentFileInfo,this.index);for(var c=0;cf;f++)e[f]=a.operate(b,c,this.rgb[f],d.rgb[f]);return new a.Color(e,this.alpha+d.alpha)},toRGB:function(){return"#"+this.rgb.map(function(a){return a=Math.round(a),a=(a>255?255:0>a?0:a).toString(16),1===a.length?"0"+a:a}).join("")},toHSL:function(){var a,b,c=this.rgb[0]/255,d=this.rgb[1]/255,e=this.rgb[2]/255,f=this.alpha,g=Math.max(c,d,e),h=Math.min(c,d,e),i=(g+h)/2,j=g-h;if(g===h)a=b=0;else{switch(b=i>.5?j/(2-g-h):j/(g+h),g){case c:a=(d-e)/j+(e>d?6:0);break;case d:a=(e-c)/j+2;break;case e:a=(c-d)/j+4}a/=6}return{h:360*a,s:b,l:i,a:f}},toHSV:function(){var a,b,c=this.rgb[0]/255,d=this.rgb[1]/255,e=this.rgb[2]/255,f=this.alpha,g=Math.max(c,d,e),h=Math.min(c,d,e),i=g,j=g-h;if(b=0===g?0:j/g,g===h)a=0;else{switch(g){case c:a=(d-e)/j+(e>d?6:0);break;case d:a=(e-c)/j+2;break;case e:a=(c-d)/j+4}a/=6}return{h:360*a,s:b,v:i,a:f}},toARGB:function(){var a=[Math.round(255*this.alpha)].concat(this.rgb);return"#"+a.map(function(a){return a=Math.round(a),a=(a>255?255:0>a?0:a).toString(16),1===a.length?"0"+a:a}).join("")},compare:function(a){return a.rgb?a.rgb[0]===this.rgb[0]&&a.rgb[1]===this.rgb[1]&&a.rgb[2]===this.rgb[2]&&a.alpha===this.alpha?0:-1:-1}},a.Color.fromKeyword=function(c){if(a.colors.hasOwnProperty(c))return new a.Color(a.colors[c].slice(1));if(c===b){var d=new a.Color([0,0,0],0);return d.isTransparentKeyword=!0,d}}}(c("../tree")),function(a){a.Comment=function(a,b,c,d){this.value=a,this.silent=!!b,this.currentFileInfo=d},a.Comment.prototype={type:"Comment",genCSS:function(b,c){this.debugInfo&&c.add(a.debugInfo(b,this),this.currentFileInfo,this.index),c.add(this.value.trim())},toCSS:a.toCSS,isSilent:function(a){var b=this.currentFileInfo&&this.currentFileInfo.reference&&!this.isReferenced,c=a.compress&&!this.value.match(/^\/\*!/);return this.silent||b||c},eval:function(){return this},markReferenced:function(){this.isReferenced=!0}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype={type:"Condition",accept:function(a){this.lvalue=a.visit(this.lvalue),this.rvalue=a.visit(this.rvalue)},eval:function(a){var b,c=this.lvalue.eval(a),d=this.rvalue.eval(a),e=this.index;return b=function(a){switch(a){case"and":return c&&d;case"or":return c||d;default:if(c.compare)b=c.compare(d);else{if(!d.compare)throw{type:"Type",message:"Unable to perform comparison",index:e};b=d.compare(c)}switch(b){case-1:return"<"===a||"=<"===a||"<="===a;case 0:return"="===a||">="===a||"=<"===a||"<="===a;case 1:return">"===a||">="===a}}}(this.op),this.negate?!b:b}}}(c("../tree")),function(a){a.Dimension=function(c,d){this.value=parseFloat(c),this.unit=d&&d instanceof a.Unit?d:new a.Unit(d?[d]:b)},a.Dimension.prototype={type:"Dimension",accept:function(a){this.unit=a.visit(this.unit)},eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},genCSS:function(a,b){if(a&&a.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var c=this.value,d=String(c);if(0!==c&&1e-6>c&&c>-1e-6&&(d=c.toFixed(20).replace(/0+$/,"")),a&&a.compress){if(0===c&&this.unit.isLength())return b.add(d),void 0;c>0&&1>c&&(d=d.substr(1))}b.add(d),this.unit.genCSS(a,b)},toCSS:a.toCSS,operate:function(b,c,d){var e=a.operate(b,c,this.value,d.value),f=this.unit.clone();if("+"===c||"-"===c)if(0===f.numerator.length&&0===f.denominator.length)f.numerator=d.unit.numerator.slice(0),f.denominator=d.unit.denominator.slice(0);else if(0===d.unit.numerator.length&&0===f.denominator.length);else{if(d=d.convertTo(this.unit.usedUnits()),b.strictUnits&&d.unit.toString()!==f.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+f.toString()+"' and '"+d.unit.toString()+"'.");e=a.operate(b,c,this.value,d.value)}else"*"===c?(f.numerator=f.numerator.concat(d.unit.numerator).sort(),f.denominator=f.denominator.concat(d.unit.denominator).sort(),f.cancel()):"/"===c&&(f.numerator=f.numerator.concat(d.unit.denominator).sort(),f.denominator=f.denominator.concat(d.unit.numerator).sort(),f.cancel());return new a.Dimension(e,f)},compare:function(b){if(b instanceof a.Dimension){var c=this.unify(),d=b.unify(),e=c.value,f=d.value;return f>e?-1:e>f?1:d.unit.isEmpty()||0===c.unit.compare(d.unit)?0:-1}return-1},unify:function(){return this.convertTo({length:"m",duration:"s",angle:"rad"})},convertTo:function(b){var c,d,e,f,g,h=this.value,i=this.unit.clone(),j={};if("string"==typeof b){for(c in a.UnitConversions)a.UnitConversions[c].hasOwnProperty(b)&&(j={},j[c]=b);b=j}g=function(a,b){return e.hasOwnProperty(a)?(b?h/=e[a]/e[f]:h*=e[a]/e[f],f):a};for(d in b)b.hasOwnProperty(d)&&(f=b[d],e=a.UnitConversions[d],i.map(g));return i.cancel(),new a.Dimension(h,i)}},a.UnitConversions={length:{m:1,cm:.01,mm:.001,"in":.0254,pt:.0254/72,pc:.0254/72*12},duration:{s:1,ms:.001},angle:{rad:1/(2*Math.PI),deg:1/360,grad:.0025,turn:1}},a.Unit=function(a,b,c){this.numerator=a?a.slice(0).sort():[],this.denominator=b?b.slice(0).sort():[],this.backupUnit=c},a.Unit.prototype={type:"Unit",clone:function(){return new a.Unit(this.numerator.slice(0),this.denominator.slice(0),this.backupUnit)},genCSS:function(a,b){this.numerator.length>=1?b.add(this.numerator[0]):this.denominator.length>=1?b.add(this.denominator[0]):a&&a.strictUnits||!this.backupUnit||b.add(this.backupUnit)},toCSS:a.toCSS,toString:function(){var a,b=this.numerator.join("*");for(a=0;a0)for(b=0;e>b;b++)this.numerator.push(a);else if(0>e)for(b=0;-e>b;b++)this.denominator.push(a)}0===this.numerator.length&&0===this.denominator.length&&c&&(this.backupUnit=c),this.numerator.sort(),this.denominator.sort()}}}(c("../tree")),function(a){a.Directive=function(b,c,d,e){this.name=b,Array.isArray(c)?(this.rules=[new a.Ruleset([],c)],this.rules[0].allowImports=!0):this.value=c,this.currentFileInfo=e},a.Directive.prototype={type:"Directive",accept:function(a){this.rules=a.visit(this.rules),this.value=a.visit(this.value)},genCSS:function(b,c){c.add(this.name,this.currentFileInfo,this.index),this.rules?a.outputRuleset(b,c,this.rules):(c.add(" "),this.value.genCSS(b,c),c.add(";"))},toCSS:a.toCSS,eval:function(b){var c=this;return this.rules&&(b.frames.unshift(this),c=new a.Directive(this.name,null,this.index,this.currentFileInfo),c.rules=[this.rules[0].eval(b)],c.rules[0].root=!0,b.frames.shift()),c},variable:function(b){return a.Ruleset.prototype.variable.call(this.rules[0],b)},find:function(){return a.Ruleset.prototype.find.apply(this.rules[0],arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.rules[0])},markReferenced:function(){var a,b;if(this.isReferenced=!0,this.rules)for(b=this.rules[0].rules,a=0;a":" > ","|":"|"},_outputMapCompressed:{"":""," ":" ",":":" :","+":"+","~":"~",">":">","|":"|"},genCSS:function(a,b){b.add((a.compress?this._outputMapCompressed:this._outputMap)[this.value])},toCSS:a.toCSS}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={type:"Expression",accept:function(a){this.value=a.visit(this.value)},eval:function(b){var c,d=this.parens&&!this.parensInOp,e=!1;return d&&b.inParenthesis(),this.value.length>1?c=new a.Expression(this.value.map(function(a){return a.eval(b)})):1===this.value.length?(this.value[0].parens&&!this.value[0].parensInOp&&(e=!0),c=this.value[0].eval(b)):c=this,d&&b.outOfParenthesis(),this.parens&&this.parensInOp&&!b.isMathOn()&&!e&&(c=new a.Paren(c)),c},genCSS:function(a,b){for(var c=0;c0&&c.length&&""===c[0].combinator.value&&(c[0].combinator.value=" "),d=d.concat(a[b].elements);this.selfSelectors=[{elements:d}]}}}(c("../tree")),function(a){a.Import=function(a,c,d,e,f){if(this.options=d,this.index=e,this.path=a,this.features=c,this.currentFileInfo=f,this.options.less!==b||this.options.inline)this.css=!this.options.less||this.options.inline;else{var g=this.getPath();g&&/css([\?;].*)?$/.test(g)&&(this.css=!0)}},a.Import.prototype={type:"Import",accept:function(a){this.features=a.visit(this.features),this.path=a.visit(this.path),this.options.inline||(this.root=a.visit(this.root))},genCSS:function(a,b){this.css&&(b.add("@import ",this.currentFileInfo,this.index),this.path.genCSS(a,b),this.features&&(b.add(" "),this.features.genCSS(a,b)),b.add(";"))},toCSS:a.toCSS,getPath:function(){if(this.path instanceof a.Quoted){var c=this.path.value;return this.css!==b||/(\.[a-z]*$)|([\?;].*)$/.test(c)?c:c+".less"}return this.path instanceof a.URL?this.path.value.value:null},evalForImport:function(b){return new a.Import(this.path.eval(b),this.features,this.options,this.index,this.currentFileInfo)},evalPath:function(b){var c=this.path.eval(b),d=this.currentFileInfo&&this.currentFileInfo.rootpath;if(!(c instanceof a.URL)){if(d){var e=c.value;e&&b.isPathRelative(e)&&(c.value=d+e)}c.value=b.normalizePath(c.value)}return c},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.skip)return[];if(this.options.inline){var e=new a.Anonymous(this.root,0,{filename:this.importedFilename},!0);return this.features?new a.Media([e],this.features.value):[e]}if(this.css){var f=new a.Import(this.evalPath(b),d,this.options,this.index);if(!f.css&&this.error)throw this.error;return f}return c=new a.Ruleset([],this.root.rules.slice(0)),c.evalImports(b),this.features?new a.Media(c.rules,this.features.value):c.rules}}}(c("../tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={type:"JavaScript",eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify(new a.Variable("@"+e,d.index).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: "+g.message+" from `"+f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{c=f.call(e)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message+"'",index:this.index}}return"string"==typeof c?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(c("../tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={type:"Keyword",eval:function(){return this},genCSS:function(a,b){b.add(this.value)},toCSS:a.toCSS,compare:function(b){return b instanceof a.Keyword?b.value===this.value?0:1:-1}},a.True=new a.Keyword("true"),a.False=new a.Keyword("false")}(c("../tree")),function(a){a.Media=function(b,c,d,e){this.index=d,this.currentFileInfo=e;var f=this.emptySelectors();this.features=new a.Value(c),this.rules=[new a.Ruleset(f,b)],this.rules[0].allowImports=!0},a.Media.prototype={type:"Media",accept:function(a){this.features=a.visit(this.features),this.rules=a.visit(this.rules)},genCSS:function(b,c){c.add("@media ",this.currentFileInfo,this.index),this.features.genCSS(b,c),a.outputRuleset(b,c,this.rules)},toCSS:a.toCSS,eval:function(b){b.mediaBlocks||(b.mediaBlocks=[],b.mediaPath=[]);var c=new a.Media([],[],this.index,this.currentFileInfo);this.debugInfo&&(this.rules[0].debugInfo=this.debugInfo,c.debugInfo=this.debugInfo);var d=!1;b.strictMath||(d=!0,b.strictMath=!0);try{c.features=this.features.eval(b)}finally{d&&(b.strictMath=!1)}return b.mediaPath.push(c),b.mediaBlocks.push(c),b.frames.unshift(this.rules[0]),c.rules=[this.rules[0].eval(b)],b.frames.shift(),b.mediaPath.pop(),0===b.mediaPath.length?c.evalTop(b):c.evalNested(b)},variable:function(b){return a.Ruleset.prototype.variable.call(this.rules[0],b)},find:function(){return a.Ruleset.prototype.find.apply(this.rules[0],arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.rules[0])},emptySelectors:function(){var b=new a.Element("","&",this.index,this.currentFileInfo);return[new a.Selector([b],null,null,this.index,this.currentFileInfo)]},markReferenced:function(){var a,b=this.rules[0].rules;for(this.isReferenced=!0,a=0;a1){var d=this.emptySelectors();c=new a.Ruleset(d,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(0===a.length)return[];if(1===a.length)return a[0];for(var b=[],c=this.permute(a.slice(1)),d=0;d0){for(j=!0,g=0;gthis.params.length)return!1}c=Math.min(d,this.arity);for(var e=0;c>e;e++)if(!this.params[e].name&&!this.params[e].variadic&&a[e].value.eval(b).toCSS()!=this.params[e].value.eval(b).toCSS())return!1;return!0}}}(c("../tree")),function(a){a.Negative=function(a){this.value=a},a.Negative.prototype={type:"Negative",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add("-"),this.value.genCSS(a,b)},toCSS:a.toCSS,eval:function(b){return b.isMathOn()?new a.Operation("*",[new a.Dimension(-1),this.value]).eval(b):new a.Negative(this.value.eval(b))}}}(c("../tree")),function(a){a.Operation=function(a,b,c){this.op=a.trim(),this.operands=b,this.isSpaced=c},a.Operation.prototype={type:"Operation",accept:function(a){this.operands=a.visit(this.operands)},eval:function(b){var c,d=this.operands[0].eval(b),e=this.operands[1].eval(b);if(b.isMathOn()){if(d instanceof a.Dimension&&e instanceof a.Color){if("*"!==this.op&&"+"!==this.op)throw{type:"Operation",message:"Can't substract or divide a color from a number"};c=e,e=d,d=c}if(!d.operate)throw{type:"Operation",message:"Operation on an invalid type"};return d.operate(b,this.op,e)}return new a.Operation(this.op,[d,e],this.isSpaced)},genCSS:function(a,b){this.operands[0].genCSS(a,b),this.isSpaced&&b.add(" "),b.add(this.op),this.isSpaced&&b.add(" "),this.operands[1].genCSS(a,b)},toCSS:a.toCSS},a.operate=function(a,b,c,d){switch(b){case"+":return c+d;case"-":return c-d;case"*":return c*d;case"/":return c/d}}}(c("../tree")),function(a){a.Paren=function(a){this.value=a},a.Paren.prototype={type:"Paren",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add("("),this.value.genCSS(a,b),b.add(")")},toCSS:a.toCSS,eval:function(b){return new a.Paren(this.value.eval(b))}}}(c("../tree")),function(a){a.Quoted=function(a,b,c,d,e){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d,this.currentFileInfo=e},a.Quoted.prototype={type:"Quoted",genCSS:function(a,b){this.escaped||b.add(this.quote,this.currentFileInfo,this.index),b.add(this.value),this.escaped||b.add(this.quote)},toCSS:a.toCSS,eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return new a.JavaScript(e,c.index,!0).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=new a.Variable("@"+e,c.index,c.currentFileInfo).eval(b,!0);return f instanceof a.Quoted?f.value:f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},compare:function(a){if(!a.toCSS)return-1;var b=this.toCSS(),c=a.toCSS();return b===c?0:c>b?-1:1}}}(c("../tree")),function(a){a.Rule=function(b,c,d,e,f,g,h){this.name=b,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.merge=e,this.index=f,this.currentFileInfo=g,this.inline=h||!1,this.variable="@"===b.charAt(0)},a.Rule.prototype={type:"Rule",accept:function(a){this.value=a.visit(this.value)},genCSS:function(a,b){b.add(this.name+(a.compress?":":": "),this.currentFileInfo,this.index);try{this.value.genCSS(a,b)}catch(c){throw c.index=this.index,c.filename=this.currentFileInfo.filename,c}b.add(this.important+(this.inline||a.lastRule&&a.compress?"":";"),this.currentFileInfo,this.index)},toCSS:a.toCSS,eval:function(b){var c=!1;"font"!==this.name||b.strictMath||(c=!0,b.strictMath=!0);try{return new a.Rule(this.name,this.value.eval(b),this.important,this.merge,this.index,this.currentFileInfo,this.inline)}finally{c&&(b.strictMath=!1)}},makeImportant:function(){return new a.Rule(this.name,this.value,"!important",this.merge,this.index,this.currentFileInfo,this.inline)}}}(c("../tree")),function(a){a.Ruleset=function(a,b,c){this.selectors=a,this.rules=b,this._lookups={},this.strictImports=c},a.Ruleset.prototype={type:"Ruleset",accept:function(a){if(this.paths)for(var b=0;bd?Array.prototype.push.apply(e,f.find(new a.Selector(b.elements.slice(d)),c)):e.push(f);break}}),this._lookups[f]=e)},genCSS:function(b,c){var d,e,f,g,h,i=[],j=[],k=!0;b.tabLevel=b.tabLevel||0,this.root||b.tabLevel++;var l=b.compress?"":Array(b.tabLevel+1).join(" "),m=b.compress?"":Array(b.tabLevel).join(" ");for(d=0;d0&&this.mergeElementsOnToSelectors(r,i),f=0;f0&&(k[0].elements=k[0].elements.slice(0),k[0].elements.push(new a.Element(j.combinator,"",0,j.index,j.currentFileInfo))),s.push(k);else for(g=0;g0?(m=k.slice(0),q=m.pop(),o=d.createDerived(q.elements.slice(0)),p=!1):o=d.createDerived([]),l.length>1&&(n=n.concat(l.slice(1))),l.length>0&&(p=!1,o.elements.push(new a.Element(j.combinator,l[0].elements[0].value,j.index,j.currentFileInfo)),o.elements=o.elements.concat(l[0].elements.slice(1))),p||m.push(o),m=m.concat(n),s.push(m);i=s,r=[]}for(r.length>0&&this.mergeElementsOnToSelectors(r,i),e=0;e0&&b.push(i[e])}else if(c.length>0)for(e=0;e0?e[e.length-1]=e[e.length-1].createDerived(e[e.length-1].elements.concat(b)):e.push(new a.Selector(b))}}}(c("../tree")),function(a){a.Selector=function(a,b,c,d,e,f){this.elements=a,this.extendList=b||[],this.condition=c,this.currentFileInfo=e||{},this.isReferenced=f,c||(this.evaldCondition=!0)},a.Selector.prototype={type:"Selector",accept:function(a){this.elements=a.visit(this.elements),this.extendList=a.visit(this.extendList),this.condition=a.visit(this.condition)},createDerived:function(b,c,d){d=null!=d?d:this.evaldCondition;var e=new a.Selector(b,c||this.extendList,this.condition,this.index,this.currentFileInfo,this.isReferenced);return e.evaldCondition=d,e},match:function(a){var b,c,d,e,f=this.elements,g=f.length;if(b=a.elements.slice(a.elements.length&&"&"===a.elements[0].value?1:0),c=b.length,d=Math.min(g,c),0===c||c>g)return 0;for(e=0;d>e;e++)if(f[e].value!==b[e].value)return 0;return d},eval:function(a){var b=this.condition&&this.condition.eval(a);return this.createDerived(this.elements.map(function(b){return b.eval(a)}),this.extendList.map(function(b){return b.eval(a)}),b)},genCSS:function(a,b){var c,d;if(a&&a.firstSelector||""!==this.elements[0].combinator.value||b.add(" ",this.currentFileInfo,this.index),!this._css)for(c=0;c0)&&e.splice(0,0,b);else{b.paths=b.paths.filter(function(b){var c;for(" "===b[0].elements[0].combinator.value&&(b[0].elements[0].combinator=new a.Combinator("")),c=0;c0&&b.accept(this._visitor),c.visitDeeper=!1,this._mergeRules(b.rules),this._removeDuplicateRules(b.rules),b.rules.length>0&&b.paths.length>0&&e.splice(0,0,b)}return 1===e.length?e[0]:e},_removeDuplicateRules:function(b){var c,d,e,f={};for(e=b.length-1;e>=0;e--)if(d=b[e],d instanceof a.Rule)if(f[d.name]){c=f[d.name],c instanceof a.Rule&&(c=f[d.name]=[f[d.name].toCSS(this._env)]);var g=d.toCSS(this._env);-1!==c.indexOf(g)?b.splice(e,1):c.push(g)}else f[d.name]=d},_mergeRules:function(b){for(var c,d,e,f={},g=0;g1&&(d=c[0],d.value=new a.Value(c.map(function(a){return a.value})))})}}}(c("./tree")),function(a){a.extendFinderVisitor=function(){this._visitor=new a.visitor(this),this.contexts=[],this.allExtendsStack=[[]]},a.extendFinderVisitor.prototype={run:function(a){return a=this._visitor.visit(a),a.allExtends=this.allExtendsStack[0],a},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitRuleset:function(b){if(!b.root){var c,d,e,f,g=[];for(c=0;c100){var o="{unable to calculate}",p="{unable to calculate}";try{o=m[0].selfSelectors[0].toCSS(),p=m[0].selector.toCSS()}catch(q){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+o+":extend("+p+")"}}return m.concat(n.doExtendChaining(m,c,d+1))}return m},inInheritanceChain:function(a,b){if(a===b)return!0;if(b.parents){if(this.inInheritanceChain(a,b.parents[0]))return!0;if(this.inInheritanceChain(a,b.parents[1]))return!0}return!1},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitSelector:function(a,b){b.visitDeeper=!1},visitRuleset:function(a){if(!a.root){var b,c,d,e,f=this.allExtendsStack[this.allExtendsStack.length-1],g=[],h=this;for(d=0;d0&&k[i.matched].combinator.value!==g?i=null:i.matched++,i&&(i.finished=i.matched===k.length,i.finished&&!a.allowAfter&&(e+1j&&k>0&&(l[l.length-1].elements=l[l.length-1].elements.concat(c[j].elements.slice(k)),k=0,j++),i=f.elements.slice(k,h.index).concat([g]).concat(d.elements.slice(1)),j===h.pathIndex&&e>0?l[l.length-1].elements=l[l.length-1].elements.concat(i):(l=l.concat(c.slice(j,h.pathIndex)),l.push(new a.Selector(i))),j=h.endPathIndex,k=h.endPathElementIndex,k>=c[j].elements.length&&(k=0,j++);return j0&&(l[l.length-1].elements=l[l.length-1].elements.concat(c[j].elements.slice(k)),j++),l=l.concat(c.slice(j,c.length))},visitRulesetOut:function(){},visitMedia:function(a){var b=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);b=b.concat(this.doExtendChaining(b,a.allExtends)),this.allExtendsStack.push(b)},visitMediaOut:function(){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(a){var b=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);b=b.concat(this.doExtendChaining(b,a.allExtends)),this.allExtendsStack.push(b)},visitDirectiveOut:function(){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(c("./tree")),function(a){a.sourceMapOutput=function(a){this._css=[],this._rootNode=a.rootNode,this._writeSourceMap=a.writeSourceMap,this._contentsMap=a.contentsMap,this._sourceMapFilename=a.sourceMapFilename,this._outputFilename=a.outputFilename,this._sourceMapURL=a.sourceMapURL,this._sourceMapBasepath=a.sourceMapBasepath,this._sourceMapRootpath=a.sourceMapRootpath,this._outputSourceFiles=a.outputSourceFiles,this._sourceMapGeneratorConstructor=a.sourceMapGenerator||c("source-map").SourceMapGenerator,this._sourceMapRootpath&&"/"!==this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1)&&(this._sourceMapRootpath+="/"),this._lineNumber=0,this._column=0},a.sourceMapOutput.prototype.normalizeFilename=function(a){return this._sourceMapBasepath&&0===a.indexOf(this._sourceMapBasepath)&&(a=a.substring(this._sourceMapBasepath.length),("\\"===a.charAt(0)||"/"===a.charAt(0))&&(a=a.substring(1))),(this._sourceMapRootpath||"")+a.replace(/\\/g,"/")},a.sourceMapOutput.prototype.add=function(a,b,c,d){if(a){var e,f,g,h,i;if(b){var j=this._contentsMap[b.filename].substring(0,c);f=j.split("\n"),h=f[f.length-1]}if(e=a.split("\n"),g=e[e.length-1],b)if(d)for(i=0;i0){var c,d=JSON.stringify(this._sourceMapGenerator.toJSON());this._sourceMapURL?c=this._sourceMapURL:this._sourceMapFilename&&(c=this.normalizeFilename(this._sourceMapFilename)),this._writeSourceMap?this._writeSourceMap(d):c="data:application/json,"+encodeURIComponent(d),c&&this._css.push("/*# sourceMappingURL="+c+" */")}return this._css.join("")}}(c("./tree"));var y=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);w.env=w.env||("127.0.0.1"==location.hostname||"0.0.0.0"==location.hostname||"localhost"==location.hostname||location.port&&location.port.length>0||y?"development":"production");var z={info:2,errors:1,none:0};if(w.logLevel="undefined"!=typeof w.logLevel?w.logLevel:z.info,w.async=w.async||!1,w.fileAsync=w.fileAsync||!1,w.poll=w.poll||(y?1e3:1500),w.functions)for(var A in w.functions)w.tree.functions[A]=w.functions[A];var B=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);B&&(w.dumpLineNumbers=B[1]);var C=/^text\/(x-)?less$/,D=null,E={},F="";if(w.watch=function(){return w.watchMode||(w.env="development",u()),this.watchMode=!0},w.unwatch=function(){return clearInterval(w.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&w.watch(),"development"!=w.env)try{D="undefined"==typeof a.localStorage?null:a.localStorage}catch(G){}var H=document.getElementsByTagName("link");w.sheets=[];for(var I=0;I>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof(window) === 'undefined') { + if (typeof(exports) === 'undefined') { + // Rhino + less = {}; + tree = less.tree = {}; + } else { + // Node.js + less = exports, + tree = require('less/tree'); + } +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[A-Za-z-]+/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e) } + + if (c.value && c.value[0] === '&') { + return new(tree.Element)(c, null); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + if (match = /^([.#: \w-]+)[\s\n]*\{/.exec(chunks[j])) { + i += match[0].length - 1; + selectors = [new(tree.Selector)([new(tree.Element)(null, match[1])])]; + } else { + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page|@-[-a-z]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (typeof(window) !== 'undefined' /* browser */ || typeof(exports) === 'undefined' /* rhino */) { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('less/tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else if (rgb.length == 8) { + this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0; + this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + + +})(require('less/tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Element = function (combinator, value) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('less/tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('less/tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('less/tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('less/tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function( paths, context, selectors ) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function( paths, context, selector ) { + var before = [], after = [], beforeElements = [], afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value[0] === '&') { + hasParentSelector = true; + } + if(!hasParentSelector) { + beforeElements.push(el); + } else { + afterElements.push(el); + } + } + + if(!hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if(beforeElements.length > 0) { + before.push(new (tree.Selector)(beforeElements)); + } + if(afterElements.length > 0) { + after.push(new (tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('less/tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + if (this.elements[0].value === other.elements[0].value) { + return true; + } else { + return false; + } +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('less/tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/|file:\/|data:\/)?\//.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('less/tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('less/tree')); +require('less/tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('less/tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; + var input = readFile(sheetName); + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + print("Error: " + e); + quit(1); + } + callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); + }); + + // callback({}, sheet, { local: true, remaining: remaining }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + name = args[0]; + var output = args[1]; + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + quit(1); + } else { + result = root.toCSS(); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + print("done"); +}(arguments)); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.1.5.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.1.5.js new file mode 100644 index 000000000..e755f6310 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.1.5.js @@ -0,0 +1,2481 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + less = {}; + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'rhino'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + mime: env && env.mime, // MIME type of .less files + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + that.files[path] = root; // Store the root + + callback(root); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; + + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + level = 0, + match, + chunk = chunks[0], + inParam, + inString; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = i; + + if (!inString && !inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + if (c === '{' && !inString && !inParam) { level ++; + chunk.push(c); + } else if (c === '}' && !inString && !inParam) { level --; + chunk.push(c); + chunks[++j] = chunk = []; + } else if (c === '(' && !inString && !inParam) { + chunk.push(c); + inParam = true; + } else if (c === ')' && !inString && inParam) { + chunk.push(c); + inParam = false; + } else { + if (c === '"' || c === "'" || c === '`') { + if (! inString) { + inString = c; + } else { + inString = inString === c ? false : inString; + } + } + chunk.push(c); + } + } + if (level > 0) { + throw { + type: 'Syntax', + message: "Missing closing `}`", + filename: env.filename + }; + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = []; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + lines = input.split('\n'); + line = getLine(e.index); + + for (var n = e.index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + throw { + type: e.type, + message: e.message, + filename: env.filename, + index: e.index, + line: typeof(line) === 'number' ? line + 1 : null, + callLine: e.call && (getLine(e.call) + 1), + callExtract: lines[getLine(e.call)], + stack: e.stack, + column: column, + extract: [ + lines[line - 1], + lines[line], + lines[line + 1] + ] + }; + } + if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + + function getLine(index) { + return index ? (input.slice(0, index).match(/\n/g) || "").length : null; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + name: "ParseError", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { return new(tree.Keyword)(k) } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, index = i; + + if (! (name = /^([\w-]+|%)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { return $(this.alpha) } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + if (! $(')')) throw new(Error)("missing closing ) for url()"); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i); + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + $('(') && (args = $(this.entities.arguments)) && $(')'); + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index); + } + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value; + + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; + + while (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + params.push({ name: param.name, value: value }); + } else { + throw new(Error)("Expected value"); + } + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + if (! $(')')) throw new(Error)("missing closing ) for alpha()"); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (c === ':' && input.charAt(i + 1) === ':') { + i += 2; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)('::'); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path; + if ($(/^@import\s+/) && + (path = $(this.entities.quoted) || $(this.entities.url)) && + $(';')) { + return new(tree.Import)(path, imports); + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import'])) { + return value; + } else if (name = $(/^@media|@page/) || $(/^@(?:-webkit-|-moz-)?keyframes/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (path.charAt(0) !== '/' && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, callback, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math.round(number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math.round(n); + } else { + throw { + error: "RuntimeError", + message: "math functions take numbers as parameters" + }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { message: "error evaluating function `" + this.name + "`", + index: this.index }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + this.value = value ? value.trim() : ""; + this.index = index; +}; +tree.Element.prototype.toCSS = function (env) { + return this.combinator.toCSS(env || {}) + this.value; +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '::': '::', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports) { + var that = this; + + this._path = path; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (root) { + if (! root) { + throw new(Error)("Error parsing " + that.path); + } + that.root = root; + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function () { + if (this.css) { + return "@import " + this._path.toCSS() + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments).rules); + match = true; + } catch (e) { + throw { message: e.message, index: e.index, stack: e.stack, call: this.index }; + } + } + } + if (match) { + return rules; + } else { + throw { message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index }; + } + } + } + throw { message: this.selector.toCSS().trim() + " is undefined", + index: this.index }; + } +}; + +tree.mixin.Definition = function (name, params, rules) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + eval: function (env, args) { + var frame = new(tree.Ruleset)(null, []), context, _arguments = []; + + for (var i = 0, val; i < this.params.length; i++) { + if (this.params[i].name) { + if (val = (args && args[i]) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env))); + } else { + throw { message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push(args[i] || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + return new(tree.Ruleset)(null, this.rules.slice(0)).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (argsLength < this.required) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return v.value || v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + ";"; + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var ruleset = new(tree.Ruleset)(this.selectors, this.rules.slice(0)); + + ruleset.root = this.root; + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; + + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); + } else { + this.joinSelectors( paths, context, this.selectors ); + } + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : (paths.length > 3 ? ',\n' : ', ')); + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; + + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; + } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (!/^(?:https?:\/\/|file:\/\/|data:)?/.test(val.value) && paths.length > 0 && typeof(window) !== 'undefined') { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index) { this.name = name, this.index = index }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { message: "variable " + name + " is undefined", + index: this.index }; + } + } +}; + +})(require('../tree')); +require('./tree').find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +require('./tree').jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; + var input = readFile(sheetName); + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + print("Error: " + e); + quit(1); + } + callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); + }); + + // callback({}, sheet, { local: true, remaining: remaining }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + name = args[0]; + var output = args[1]; + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + quit(1); + } else { + result = root.toCSS(); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + print("done"); +}(arguments)); diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.1.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.1.js new file mode 100644 index 000000000..1ebe0ea4b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.1.js @@ -0,0 +1,3725 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + if (!env.contents) { env.contents={}; } // env.contents must be passed arround with top env + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = path in that.files; + + that.files[path] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(e) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + } + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^)@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(') && (v = ($(this.entities.variableCurly) || $(this.entities.variable))) && $(')')) { + e = new(tree.Paren)(v); + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[A-Za-z][A-Za-z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + // __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __ + loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) + * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(number(n).toFixed(fraction), n.unit); + } else if (typeof(n) === 'number') { + return n.toFixed(fraction); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(hsla) { + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css(\?.*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } + } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, args, rules = [], match = false; + + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } + } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs, arg; + + for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] + + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; + } + + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (arg && arg.value) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push((args[i] && args[i].value) || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules = []; + + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + rules = []; + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = rules.concat(ruleset.rules[i].eval(env)); + } else { + rules.push(ruleset.rules[i]); + } + } + ruleset.rules = rules; + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); + + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, paths) { + this.value = val; + this.paths = paths; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx); + + // Add the base path if the URL is relative and we are in the browser + if (typeof window !== 'undefined' && typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value) && this.paths.length > 0) { + val.value = this.paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + + return new(tree.URL)(val, this.paths); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, sheet, { local: false, lastModified: 0, remaining: remaining }); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.2.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.2.js new file mode 100644 index 000000000..4b83596f7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.2.js @@ -0,0 +1,3990 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree, charset; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + // env.contents and files must be passed arround with top env + if (!env.contents) { env.contents = {}; } + env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided + if (!env.files) { env.files = {}; } + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, fullPath) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = fullPath in that.files; + + that.files[fullPath] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error, env); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + e = error || e; + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.rootpath); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + expressions = []; + while (arg = $(this.expression)) { + nameLoop = null; + value = arg; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } + } + } + + expressions.push(value); + + argsComma.push({ name: nameLoop, value: value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name: name, value: value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + expect(')'); + } + + args = isSemiColonSeperated ? argsSemiColon : argsComma; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + params.push({ variadic: true }); + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',') || $(';')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.entities.variableCurly) || + $(this.entities.variable) || + $(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ + href: path, + title: path, + type: env.mime, + contents: env.contents, + files: env.files, + rootpath: env.rootpath, + entryPath: env.entryPath, + relativeUrls: env.relativeUrls }, + function (e, root, data, sheet, _, path) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.call(null, e, root, path); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) * + color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, n); + }, + ceil: function (n) { + return this._math(Math.ceil, n); + }, + floor: function (n) { + return this._math(Math.floor, n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit == '%') { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); + + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + } + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + if (other.unit && this.unit !== other.unit) { + return -1; + } + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index, rootpath) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + this.rootpath = rootpath; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /(\.[a-z]*$)|([\?;].*)$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css([\?;].*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + // Add the base path if the import is relative + if (typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) { + this._path.value = this.rootpath + this._path.value; + } + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), varargs, arg, params = this.params.slice(0), i, j, val, name, isNamedFound, argIndex; + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, {frames: mixinFrames}, args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(mixinFrames) + }); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, {frames: this.frames.concat(env.frames)}, args, [])].concat(env.frames) + })) { return false } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { name: "OperationError", + message: "Operation on an invalid type" }; + } + + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Rule.prototype.makeImportant = function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(paths, env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen) + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, rootpath) { + this.value = val; + this.rootpath = rootpath; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + if (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) { + rootpath = this.rootpath; + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, this.rootpath); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.3.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.3.js new file mode 100644 index 000000000..857a97c94 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.3.3.js @@ -0,0 +1,4002 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree, charset; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + // env.contents and files must be passed arround with top env + if (!env.contents) { env.contents = {}; } + env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided + if (!env.files) { env.files = {}; } + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, fullPath) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = fullPath in that.files; + + that.files[fullPath] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error, env); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + e = error || e; + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.rootpath); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + expressions = []; + while (arg = $(this.expression)) { + nameLoop = null; + value = arg; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } + } + } + + expressions.push(value); + + argsComma.push({ name: nameLoop, value: value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name: name, value: value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + expect(')'); + } + + args = isSemiColonSeperated ? argsSemiColon : argsComma; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + params.push({ variadic: true }); + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',') || $(';')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.entities.variableCurly) || + $(this.entities.variable) || + $(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + // depreciated, will be removed soon + if ($('(')) { + sel = $(this.entity); + if (!$(')')) { return null; } + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ + href: path, + title: path, + type: env.mime, + contents: env.contents, + files: env.files, + rootpath: env.rootpath, + entryPath: env.entryPath, + relativeUrls: env.relativeUrls }, + function (e, root, data, sheet, _, path) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.call(null, e, root, path); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) * + color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, n); + }, + ceil: function (n) { + return this._math(Math.ceil, n); + }, + floor: function (n) { + return this._math(Math.floor, n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit == '%') { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }), + result; + + if (this.name in tree.functions) { // 1. + try { + result = tree.functions[this.name].apply(tree.functions, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = unit || null; +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; + } else { + if (other.unit && this.unit !== other.unit) { + return -1; + } + return 0; + } + } else { + return -1; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index, rootpath) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + this.rootpath = rootpath; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /(\.[a-z]*$)|([\?;].*)$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css([\?;].*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + // Add the base path if the import is relative + if (typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) { + this._path.value = this.rootpath + this._path.value; + } + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), varargs, arg, params = this.params.slice(0), i, j, val, name, isNamedFound, argIndex; + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, {frames: mixinFrames}, args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(mixinFrames) + }); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, {frames: this.frames.concat(env.frames)}, args, [])].concat(env.frames) + })) { return false } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { name: "OperationError", + message: "Operation on an invalid type" }; + } + + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Rule.prototype.makeImportant = function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(paths, env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements) { + this.elements = elements; +}; +tree.Selector.prototype.match = function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen) + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, rootpath) { + this.value = val; + this.rootpath = rootpath; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + if (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) { + rootpath = this.rootpath; + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, this.rootpath); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.4.0.js b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.4.0.js new file mode 100644 index 000000000..a90573f7f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/dist/less-rhino-1.4.0.js @@ -0,0 +1,4273 @@ +// +// Stub out `require` in rhino +// +function require(arg) { + return less[arg.split('/')[1]]; +}; + + +// ecma-5.js +// +// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License +// -- tlrobinson Tom Robinson +// dantman Daniel Friesen + +// +// Array +// +if (!Array.isArray) { + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; +} +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; + + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); + } + } + return res; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); + } + } + return values; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; + + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); + + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); + } + } + return rv; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; + + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; + + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; +} + +// +// Object +// +if (!Object.keys) { + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); + } + } + return keys; + }; +} + +// +// String +// +if (!String.prototype.trim) { + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; +} +var less, tree, charset; + +if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; +} else if (typeof(window) === 'undefined') { + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; +} else { + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; + + var that = this; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed arround by reference. + var env = env || { }; + // env.contents and files must be passed arround with top env + if (!env.contents) { env.contents = {}; } + env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided + if (!env.files) { env.files = {}; } + + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); + + // + // Import a file asynchronously + // + less.Parser.importer(path, this.paths, function (e, root, fullPath) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = fullPath in that.files; + + that.files[fullPath] = root; // Store the root + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getFileName(e) { + if(less.mode === 'browser' || less.mode === 'rhino') + return e.filename; + else + return require('path').resolve(e.filename); + } + + function getDebugInfo(index, inputStream, e) { + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: getFileName(e) + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + this.env.filename = this.env.filename || null; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(error, env); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + var frames = [], importError; + + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers }); + } catch (e) { + throw new(LessError)(e, env); + } + + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function (e) { + e = error || e; + if (e) callback(e); + else callback(null, root); + }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.ratio) || + $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.rootpath); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A Ratio + // + // 16/9 + // + ratio: function () { + var value, c = input.charCodeAt(i); + if (c > 57 || c < 48) return; + + if (value = $(/^(\d+\/\d+)/)) { + return new(tree.Ratio)(value[1]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + save(); + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + + restore(); + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements = [], e, args, index = i; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(null, e, i)); + } + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return new(tree.Extend)(elements, index); + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + expressions = []; + while (arg = $(this.expression)) { + nameLoop = null; + value = arg; + + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } + } + } + + expressions.push(value); + + argsComma.push({ name: nameLoop, value: value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name: name, value: value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + expect(')'); + } + + args = isSemiColonSeperated ? argsSemiColon : argsComma; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + + restore(); + }, + + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + do { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + params.push({ variadic: true }); + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; + } else { + params.push({ name: param.name }); + } + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',') || $(';')) + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = (//$(this.entities.variableCurly) || + $(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match, extend; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (!e) { + break; + } + c = input.charAt(i); + elements.push(e) + e = null; + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extend) } + if (extend) { error("Extend must be used to extend a selector"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import(?:-(once|multiple))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + var importOnce = dir[1] !== 'multiple'; + return new(tree.Import)(path, imports, features, importOnce, index, env.rootpath); + } + } + + restore(); + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ + href: path, + title: path, + type: env.mime, + contents: env.contents, + files: env.files, + rootpath: env.rootpath, + entryPath: env.entryPath, + relativeUrls: env.relativeUrls }, + function (e, root, data, sheet, _, path) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.call(null, e, root, path); + } + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) + + 0.7152 * (color.rgb[1]/255) + + 0.0722 * (color.rgb[2]/255)) * + color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = threshold.value; + } + if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, n); + }, + ceil: function (n) { + return this._math(Math.ceil, n); + }, + floor: function (n) { + return this._math(Math.floor, n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit.is('px') ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit.is('%') ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit.is('em') ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + } +}; + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, filename) { + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; +}; +tree.Call.prototype = { + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }), + result; + + if (this.name in tree.functions) { // 1. + try { + result = tree.functions[this.name].apply(tree.functions, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env) }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + eval: function () { return this }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype.eval = function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + return this.unit.isEmpty() ? this.value : + (String(this.value) + this.unit.toCSS()); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (op, other) { + var value = tree.operate(op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(other.unit.toCSS() !== unit.toCSS()) { + throw new Error("Incompatible units: '" + unit.toCSS() + + "' and '" + other.unit.toCSS() + "'."); + } + + value = tree.operate(op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + } +}; + +tree.Unit = function (numerator, denominator) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; +}; + +tree.Unit.prototype = { + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0)); + }, + + toCSS: function () { + var i, css = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + css += "/" + this.denominator[i]; + } + return css; + }, + + compare: function (other) { + return this.is(other.toCSS()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toCSS() === unitString; + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype.eval = function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); +}; +tree.Element.prototype.toCSS = function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype.toCSS = function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value }; +tree.Expression.prototype = { + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(elements, index) { + this.selector = new(tree.Selector)(elements); + this.index = index; +}; + +tree.Extend.prototype.eval = function Extend_eval(env, selectors) { + var selfSelectors = findSelfSelectors(selectors || env.selectors), + targetValue = this.selector.elements[0].value; + + env.frames.forEach(function(frame) { + frame.rulesets().forEach(function(rule) { + rule.selectors.forEach(function(selector) { + selector.elements.forEach(function(element, idx) { + if (element.value === targetValue) { + selfSelectors.forEach(function(_selector) { + _selector.elements[0] = new tree.Element( + element.combinator, + _selector.elements[0].value, + _selector.elements[0].index + ); + rule.selectors.push(new tree.Selector( + selector.elements + .slice(0, idx) + .concat(_selector.elements) + .concat(selector.elements.slice(idx + 1)) + )); + }); + } + }); + }); + }); + }); + return this; +}; + +function findSelfSelectors(selectors) { + var ret = []; + + (function loop(elem, i) { + if (selectors[i] && selectors[i].length) { + selectors[i].forEach(function(s) { + loop(s.elements.concat(elem), i + 1); + }); + } + else { + ret.push({ elements: elem }); + } + })([], 0); + + return ret; +} + + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, imports, features, once, index, rootpath) { + var that = this; + + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); + this.rootpath = rootpath; + + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /(\.[a-z]*$)|([\?;].*)$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } + + this.css = /css([\?;].*)?$/.test(this.path); + + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + // Add the base path if the import is relative + if (typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) { + this._path.value = this.rootpath + this._path.value; + } + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); + + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + media.features = this.features.eval(env); + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, filename, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; +}; +tree.mixin.Call.prototype = { + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), varargs, arg, params = this.params.slice(0), i, j, val, name, isNamedFound, argIndex; + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, {frames: mixinFrames}, args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(mixinFrames) + }); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, {frames: this.frames.concat(env.frames)}, args, [])].concat(env.frames) + })) { return false } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands) { + this.op = op.trim(); + this.operands = operands; +}; +tree.Operation.prototype.eval = function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { name: "OperationError", + message: "Operation on an invalid type" }; + } + + return a.operate(this.op, b); +}; + +tree.operate = function (op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, i) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; +}; +tree.Quoted.prototype = { + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ratio = function (value) { + this.value = value; +}; +tree.Ratio.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; +tree.Rule.prototype.toCSS = function (env) { + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } +}; + +tree.Rule.prototype.eval = function (context) { + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); +}; + +tree.Rule.prototype.makeImportant = function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.inline); +}; + +tree.Shorthand = function (a, b) { + this.a = a; + this.b = b; +}; + +tree.Shorthand.prototype = { + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + if (this.selectors) { + for (var i = 0; i < this.selectors.length; i++) { + if (this.selectors[i].extend) { + this.selectors[i].extend.eval(env, [[this.selectors[i]]].concat(env.selectors.slice(1))); + } + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + if (! this.root) { + this.joinSelectors(paths, context, this.selectors); + } + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(paths, env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + paths.push(newSelectors[i]); + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extend) { + this.elements = elements; + this.extend = extend; +}; +tree.Selector.prototype.match = function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen) + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; +}; +tree.Selector.prototype.eval = function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extend); +}; +tree.Selector.prototype.toCSS = function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, rootpath) { + this.value = val; + this.rootpath = rootpath; +}; +tree.URL.prototype = { + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + if (typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) { + rootpath = this.rootpath; + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, this.rootpath); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; + this.is = 'value'; +}; +tree.Value.prototype = { + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; +tree.Variable.prototype = { + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +var name; + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/browser.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/browser.js new file mode 100644 index 000000000..beeb82c06 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/browser.js @@ -0,0 +1,687 @@ +// +// browser.js - client-side engine +// +/*global less, window, document, XMLHttpRequest, location */ + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + (location.port && + location.port.length > 0) || + isFileProtocol ? 'development' + : 'production'); + +var logLevel = { + info: 2, + errors: 1, + none: 0 +}; + +// The amount of logging in the javascript console. +// 2 - Information and errors +// 1 - Errors +// 0 - None +// Defaults to 2 +less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : logLevel.info; + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +var typePattern = /^text\/(x-)?less$/; +var cache = null; +var fileCache = {}; +var varsPre = ""; + +function log(str, level) { + if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) { + console.log('less: ' + str); + } +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function errorConsole(e, rootHref) { + var template = '{line} {content}'; + var filename = e.filename || rootHref; + var errors = []; + var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + " in " + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + errors.join('\n'); + } else if (e.stack) { + content += e.stack; + } + log(content, logLevel.errors); +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss === null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + if (nextEl) { + nextEl.parentNode.insertBefore(css, nextEl); + } else { + head.appendChild(css); + } + } + if (oldCss && keepOldCss === false) { + oldCss.parentNode.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.', logLevel.info); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save', logLevel.errors); + } + } +} + +function errorHTML(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, errors = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + errors.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +function error(e, rootHref) { + if (!less.errorReporting || less.errorReporting === "html") { + errorHTML(e, rootHref); + } else if (less.errorReporting === "console") { + errorConsole(e, rootHref); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("add", e, rootHref); + } +} + +function removeErrorHTML(path) { + var node = document.getElementById('less-error-message:' + extractId(path)); + if (node) { + node.parentNode.removeChild(node); + } +} + +function removeErrorConsole(path) { + //no action +} + +function removeError(path) { + if (!less.errorReporting || less.errorReporting === "html") { + removeErrorHTML(path); + } else if (less.errorReporting === "console") { + removeErrorConsole(path); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("remove", path); + } +} + +function loadStyles(newVars) { + var styles = document.getElementsByTagName('style'), + style; + for (var i = 0; i < styles.length; i++) { + style = styles[i]; + if (style.type.match(typePattern)) { + var env = new less.tree.parseEnv(less), + lessText = style.innerHTML || ''; + env.filename = document.location.href.replace(/#.*$/, ''); + + if (newVars || varsPre) { + env.useFileCache = true; + + lessText = varsPre + lessText; + + if (newVars) { + lessText += "\n" + newVars; + } + } + + /*jshint loopfunc:true */ + // use closure to store current value of i + var callback = (function(style) { + return function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }; + })(style); + new(less.Parser)(env).parse(lessText, callback); + } + } +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } else { + try { + /*global ActiveXObject */ + return new ActiveXObject("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX.", logLevel.errors); + return null; + } + } +} + +function doXHR(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + log("XHR: Getting '" + url + "'", logLevel.info); + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } +} + +function loadFile(originalHref, currentFileInfo, callback, env, newVars) { + + if (currentFileInfo && currentFileInfo.currentDirectory && !/^([a-z-]+:)?\//.test(originalHref)) { + originalHref = currentFileInfo.currentDirectory + originalHref; + } + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(originalHref, window.location.href); + var href = hrefParts.url; + var newFileInfo = { + currentDirectory: hrefParts.path, + filename: href + }; + + if (currentFileInfo) { + newFileInfo.entryPath = currentFileInfo.entryPath; + newFileInfo.rootpath = currentFileInfo.rootpath; + newFileInfo.rootFilename = currentFileInfo.rootFilename; + newFileInfo.relativeUrls = currentFileInfo.relativeUrls; + } else { + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + newFileInfo.relativeUrls = env.relativeUrls; + } + + if (newFileInfo.relativeUrls) { + if (env.rootpath) { + newFileInfo.rootpath = extractUrlParts(env.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + if (env.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + if (newVars) { + lessText += "\n" + newVars; + } + callback(null, lessText, href, newFileInfo, { lastModified: new Date() }); + } catch (e) { + callback(e, null, href); + } + return; + } + + doXHR(href, env.mime, function (data, lastModified) { + data = varsPre + data; + + // per file cache + fileCache[href] = data; + + // Use remote copy (re-parse) + try { + callback(null, data, href, newFileInfo, { lastModified: lastModified }); + } catch (e) { + callback(e, null, href); + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href); + }); +} + +function loadStyleSheet(sheet, callback, reload, remaining, newVars) { + + var env = new less.tree.parseEnv(less); + env.mime = sheet.type; + + if (newVars || varsPre) { + env.useFileCache = true; + } + + loadFile(sheet.href, null, function(e, data, path, newFileInfo, webInfo) { + + if (webInfo) { + webInfo.remaining = remaining; + + var css = cache && cache.getItem(path), + timestamp = cache && cache.getItem(path + ':timestamp'); + + if (!reload && timestamp && webInfo.lastModified && + (new(Date)(webInfo.lastModified).valueOf() === + new(Date)(timestamp).valueOf())) { + // Use local copy + createCSS(css, sheet); + webInfo.local = true; + callback(null, null, data, sheet, webInfo, path); + return; + } + } + + //TODO add tests around how this behaves when reloading + removeError(path); + + if (data) { + env.currentFileInfo = newFileInfo; + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, webInfo, path); + } catch (e) { + callback(e, null, null, sheet); + } + }); + } else { + callback(e, null, null, sheet, webInfo, path); + } + }, env, newVars); +} + +function loadStyleSheets(callback, reload, newVars) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), newVars); + } +} + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +function serializeVars(vars) { + var s = ""; + + for (var name in vars) { + s += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((vars[name].slice(-1) === ';')? vars[name] : vars[name] +';'); + } + + return s; +} + + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true; +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +less.modifyVars = function(record) { + less.refresh(false, serializeVars(record)); +}; + +less.refresh = function (reload, newVars) { + var startTime, endTime; + startTime = endTime = new Date(); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache.", logLevel.info); + } else { + log("parsed " + sheet.href + " successfully.", logLevel.info); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info); + if (env.remaining === 0) { + log("css generated in " + (new Date() - startTime) + 'ms', logLevel.info); + } + endTime = new Date(); + }, reload, newVars); + + loadStyles(newVars); +}; + +if (less.globalVars) { + varsPre = serializeVars(less.globalVars) + "\n"; +} + +less.refreshStyles = loadStyles; + +less.Parser.fileLoader = loadFile; + +less.refresh(less.env === 'development'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/colors.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/colors.js new file mode 100644 index 000000000..e509b6025 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/colors.js @@ -0,0 +1,151 @@ +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/env.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/env.js new file mode 100644 index 000000000..9e92936d7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/env.js @@ -0,0 +1,133 @@ +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'rootpath', // option - rootpath to append to URL's + 'strictImports', // option - + 'insecure', // option - whether to allow imports from insecure ssl hosts + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true + 'mime', // browser only - mime type for sheet import + 'useFileCache', // browser only - whether to use the per file session cache + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' - absolute path to the entry file + // 'reference' - whether the file should not be output and only output parts that are referenced + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'cleancss', // whether to compress with clean-css + 'sourceMap', // whether to output a source map + 'importMultiple'// whether we are currently importing multiple copies + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + tree.evalEnv.prototype.normalizePath = function( path ) { + var + segments = path.split("/").reverse(), + segment; + + path = []; + while (segments.length !== 0 ) { + segment = segments.pop(); + switch( segment ) { + case ".": + break; + case "..": + if ((path.length === 0) || (path[path.length - 1] === "..")) { + path.push( segment ); + } else { + path.pop(); + } + break; + default: + path.push( segment ); + break; + } + } + + return path.join("/"); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + }; + +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/extend-visitor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/extend-visitor.js new file mode 100644 index 000000000..d6f853cce --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/extend-visitor.js @@ -0,0 +1,420 @@ +(function (tree) { + /*jshint loopfunc:true */ + + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + rulesetNode.extendOnEveryPath = true; + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (rulesetNode.extendOnEveryPath || selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator === '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + elementValue1 = elementValue1.value; + elementValue2 = elementValue2.value; + if (elementValue1 instanceof tree.Selector) { + if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) { + return false; + } + for(var i = 0; i currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + newElements = selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)); + + if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) { + path[path.length - 1].elements = + path[path.length - 1].elements.concat(newElements); + } else { + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + newElements + )); + } + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/functions.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/functions.js new file mode 100644 index 000000000..1f63993b1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/functions.js @@ -0,0 +1,676 @@ +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; } + else if (h * 2 < 1) { return m2; } + else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; } + else { return m1; } + } + + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + // filter: saturate(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + /*jshint loopfunc:true */ + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + if(!(val instanceof tree.Dimension)) { + throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") }; + } + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + /*jshint eqnull:true */ + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + _minmax: function (isMin, args) { + args = Array.prototype.slice.call(args); + switch(args.length) { + case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 1: return args[0]; + } + var i, j, current, currentUnified, referenceUnified, unit, + order = [], // elems only contains original argument values. + values = {}; // key is the unit.toString() for unified tree.Dimension values, + // value is the index into the order array. + for (i = 0; i < args.length; i++) { + current = args[i]; + if (!(current instanceof tree.Dimension)) { + order.push(current); + continue; + } + currentUnified = current.unify(); + unit = currentUnified.unit.toString(); + j = values[unit]; + if (j === undefined) { + values[unit] = order.length; + order.push(current); + continue; + } + referenceUnified = order[j].unify(); + if ( isMin && currentUnified.value < referenceUnified.value || + !isMin && currentUnified.value > referenceUnified.value) { + order[j] = current; + } + } + if (order.length == 1) { + return order[0]; + } + args = order.map(function (a) { return a.toCSS(this.env); }) + .join(this.env.compress ? "," : ", "); + return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")"); + }, + min: function () { + return this._minmax(true, arguments); + }, + max: function () { + return this._minmax(false, arguments); + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + var colorCandidate = n.value, + returnColor; + returnColor = tree.Color.fromKeyword(colorCandidate); + if (returnColor) { + return returnColor; + } + if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) { + return new(tree.Color)(colorCandidate.slice(1)); + } + throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" }; + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + // handle non-array values as an array of length 1 + // return 'undefined' if index is invalid + return Array.isArray(values.value) + ? values.value[index] : Array(values)[index]; + }, + length: function(values) { + var n = Array.isArray(values.value) ? values.value.length : 1; + return new tree.Dimension(n); + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) { mimetype += ';base64'; } + } + else { + useBase64 = /;base64$/.test(mimetype); + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + }, + + "svg-gradient": function(direction) { + + function throwArgumentDescriptor() { + throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" }; + } + + if (arguments.length < 3) { + throwArgumentDescriptor(); + } + var stops = Array.prototype.slice.call(arguments, 1), + gradientDirectionSvg, + gradientType = "linear", + rectangleDimension = 'x="0" y="0" width="1" height="1"', + useBase64 = true, + renderEnv = {compress: false}, + returner, + directionValue = direction.toCSS(renderEnv), + i, color, position, positionValue, alpha; + + switch (directionValue) { + case "to bottom": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; + break; + case "to right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; + break; + case "to bottom right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; + break; + case "to top right": + gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; + break; + case "ellipse": + case "ellipse at center": + gradientType = "radial"; + gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; + rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; + break; + default: + throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" }; + } + returner = '' + + '' + + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; + + for (i = 0; i < stops.length; i+= 1) { + if (stops[i].value) { + color = stops[i].value[0]; + position = stops[i].value[1]; + } else { + color = stops[i]; + position = undefined; + } + + if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) { + throwArgumentDescriptor(); + } + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + alpha = color.alpha; + returner += ''; + } + returner += '' + + ''; + + if (useBase64) { + // only works in node, needs interface to what is supported in environment + try { + returner = new Buffer(returner).toString('base64'); + } catch(e) { + useBase64 = false; + } + } + + returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'"; + return new(tree.URL)(new(tree.Anonymous)(returner)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + /*jshint eqnull:true */ + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/import-visitor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/import-visitor.js new file mode 100644 index 000000000..6a3aaedfb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/import-visitor.js @@ -0,0 +1,118 @@ +(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode, + inlineCSS = importNode.options.inline; + + if (!importNode.css || inlineCSS) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + + if (importNode.options.multiple) { + env.importMultiple = true; + } + + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + + if (imported && !env.importMultiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + importNode.importedFilename = fullPath; + if (!inlineCSS && !importNode.skip) { + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + return; + } + } + + subFinish(); + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree')); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/index.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/index.js new file mode 100644 index 000000000..33eda899a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/index.js @@ -0,0 +1,224 @@ +var path = require('path'), + url = require('url'), + request, + fs = require('fs'); + +var less = { + version: [1, 5, 1], + Parser: require('./parser').Parser, + tree: require('./tree'), + render: function (input, options, callback) { + options = options || {}; + + if (typeof(options) === 'function') { + callback = options, options = {}; + } + + var parser = new(less.Parser)(options), + ee; + + if (callback) { + parser.parse(input, function (e, root) { + try { callback(e, root && root.toCSS && root.toCSS(options)); } + catch (err) { callback(err); } + }); + } else { + ee = new (require('events').EventEmitter)(); + + process.nextTick(function () { + parser.parse(input, function (e, root) { + if (e) { return ee.emit('error', e); } + try { ee.emit('success', root.toCSS(options)); } + catch (err) { ee.emit('error', err); } + }); + }); + return ee; + } + }, + formatError: function(ctx, options) { + options = options || {}; + + var message = ""; + var extract = ctx.extract; + var error = []; + var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; }; + + // only output a stack if it isn't a less error + if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); } + + if (!ctx.hasOwnProperty('index') || !extract) { + return ctx.stack || ctx.message; + } + + if (typeof(extract[0]) === 'string') { + error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); + } + + if (typeof(extract[1]) === 'string') { + var errorTxt = ctx.line + ' '; + if (extract[1]) { + errorTxt += extract[1].slice(0, ctx.column) + + stylize(stylize(stylize(extract[1][ctx.column], 'bold') + + extract[1].slice(ctx.column + 1), 'red'), 'inverse'); + } + error.push(errorTxt); + } + + if (typeof(extract[2]) === 'string') { + error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); + } + error = error.join('\n') + stylize('', 'reset') + '\n'; + + message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); + ctx.filename && (message += stylize(' in ', 'red') + ctx.filename + + stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey')); + + message += '\n' + error; + + if (ctx.callLine) { + message += stylize('from ', 'red') + (ctx.filename || '') + '/n'; + message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n'; + } + + return message; + }, + writeError: function (ctx, options) { + options = options || {}; + if (options.silent) { return; } + console.error(less.formatError(ctx, options)); + } +}; + +['color', 'directive', 'operation', 'dimension', + 'keyword', 'variable', 'ruleset', 'element', + 'selector', 'quoted', 'expression', 'rule', + 'call', 'url', 'alpha', 'import', + 'mixin', 'comment', 'anonymous', 'value', + 'javascript', 'assignment', 'condition', 'paren', + 'media', 'unicode-descriptor', 'negative', 'extend' +].forEach(function (n) { + require('./tree/' + n); +}); + + +var isUrlRe = /^(?:https?:)?\/\//i; + +less.Parser.fileLoader = function (file, currentFileInfo, callback, env) { + var pathname, dirname, data, + newFileInfo = { + relativeUrls: env.relativeUrls, + entryPath: currentFileInfo.entryPath, + rootpath: currentFileInfo.rootpath, + rootFilename: currentFileInfo.rootFilename + }; + + function handleDataAndCallCallback(data) { + var j = file.lastIndexOf('/'); + + // Pass on an updated rootpath if path of imported file is relative and file + // is in a (sub|sup) directory + // + // Examples: + // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/', + // then rootpath should become 'less/module/nav/' + // - If path of imported file is '../mixins.less' and rootpath is 'less/', + // then rootpath should become 'less/../' + if(newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) { + var relativeSubDirectory = file.slice(0, j+1); + newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file + } + newFileInfo.currentDirectory = pathname.replace(/[^\\\/]*$/, ""); + newFileInfo.filename = pathname; + + callback(null, data, pathname, newFileInfo); + } + + var isUrl = isUrlRe.test( file ); + if (isUrl || isUrlRe.test(currentFileInfo.currentDirectory)) { + if (request === undefined) { + try { request = require('request'); } + catch(e) { request = null; } + } + if (!request) { + callback({ type: 'File', message: "optional dependency 'request' required to import over http(s)\n" }); + return; + } + + var urlStr = isUrl ? file : url.resolve(currentFileInfo.currentDirectory, file), + urlObj = url.parse(urlStr); + + request.get({uri: urlStr, strictSSL: !env.insecure }, function (error, res, body) { + if (res.statusCode === 404) { + callback({ type: 'File', message: "resource '" + urlStr + "' was not found\n" }); + return; + } + if (!body) { + console.error( 'Warning: Empty body (HTTP '+ res.statusCode + ') returned by "' + urlStr +'"' ); + } + if (error) { + callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" }); + } + pathname = urlStr; + dirname = urlObj.protocol +'//'+ urlObj.host + urlObj.pathname.replace(/[^\/]*$/, ''); + handleDataAndCallCallback(body); + }); + } else { + + var paths = [currentFileInfo.currentDirectory].concat(env.paths); + paths.push('.'); + + if (env.syncImport) { + for (var i = 0; i < paths.length; i++) { + try { + pathname = path.join(paths[i], file); + fs.statSync(pathname); + break; + } catch (e) { + pathname = null; + } + } + + if (!pathname) { + callback({ type: 'File', message: "'" + file + "' wasn't found" }); + return; + } + + try { + data = fs.readFileSync(pathname, 'utf-8'); + handleDataAndCallCallback(data); + } catch (e) { + callback(e); + } + } else { + (function tryPathIndex(i) { + if (i < paths.length) { + pathname = path.join(paths[i], file); + fs.stat(pathname, function (err) { + if (err) { + tryPathIndex(i + 1); + } else { + fs.readFile(pathname, 'utf-8', function(e, data) { + if (e) { callback(e); } + handleDataAndCallCallback(data); + }); + } + }); + } else { + callback({ type: 'File', message: "'" + file + "' wasn't found" }); + } + }(0)); + } + } +}; + +require('./env'); +require('./functions'); +require('./colors'); +require('./visitor.js'); +require('./import-visitor.js'); +require('./extend-visitor.js'); +require('./join-selector-visitor.js'); +require('./to-css-visitor.js'); +require('./source-map-output.js'); + +for (var k in less) { exports[k] = less[k]; } diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/join-selector-visitor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/join-selector-visitor.js new file mode 100644 index 000000000..7c9a1af8f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/join-selector-visitor.js @@ -0,0 +1,41 @@ +(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.selectors = rulesetNode.selectors.filter(function(selector) { return selector.getIsOutput(); }); + if (rulesetNode.selectors.length === 0) { + rulesetNode.rules.length = 0; + } + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree')); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/lessc_helper.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/lessc_helper.js new file mode 100644 index 000000000..4ef768e45 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/lessc_helper.js @@ -0,0 +1,78 @@ +// lessc_helper.js +// +// helper functions for lessc +var lessc_helper = { + + //Stylize a string + stylize : function(str, style) { + var styles = { + 'reset' : [0, 0], + 'bold' : [1, 22], + 'inverse' : [7, 27], + 'underline' : [4, 24], + 'yellow' : [33, 39], + 'green' : [32, 39], + 'red' : [31, 39], + 'grey' : [90, 39] + }; + return '\033[' + styles[style][0] + 'm' + str + + '\033[' + styles[style][1] + 'm'; + }, + + //Print command line options + printUsage: function() { + console.log("usage: lessc [option option=parameter ...] [destination]"); + console.log(""); + console.log("If source is set to `-' (dash or hyphen-minus), input is read from stdin."); + console.log(""); + console.log("options:"); + console.log(" -h, --help Print help (this message) and exit."); + console.log(" --include-path=PATHS Set include paths. Separated by `:'. Use `;' on Windows."); + console.log(" -M, --depends Output a makefile import dependency list to stdout"); + console.log(" --no-color Disable colorized output."); + console.log(" --no-ie-compat Disable IE compatibility checks."); + console.log(" --no-js Disable JavaScript in less files"); + console.log(" -l, --lint Syntax check only (lint)."); + console.log(" -s, --silent Suppress output of error messages."); + console.log(" --strict-imports Force evaluation of imports."); + console.log(" --insecure Allow imports from insecure https hosts."); + console.log(" -v, --version Print version number and exit."); + console.log(" -x, --compress Compress output by removing some whitespaces."); + console.log(" --clean-css Compress output using clean-css"); + console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map)"); + console.log(" --source-map-rootpath=X adds this path onto the sourcemap filename and less file paths"); + console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory."); + console.log(" --source-map-less-inline puts the less files into the map instead of referencing them"); + console.log(" --source-map-map-inline puts the map (and any less files) into the output css file"); + console.log(" --source-map-url=URL the complete url and filename put in the less file"); + console.log(" -rp, --rootpath=URL Set rootpath for url rewriting in relative imports and urls."); + console.log(" Works with or without the relative-urls option."); + console.log(" -ru, --relative-urls re-write relative urls to the base less file."); + console.log(" -sm=on|off Turn on or off strict math, where in strict mode, math"); + console.log(" --strict-math=on|off requires brackets. This option may default to on and then"); + console.log(" be removed in the future."); + console.log(" -su=on|off Allow mixed units, e.g. 1px+1em or 1px*1px which have units"); + console.log(" --strict-units=on|off that cannot be represented."); + console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file."); + console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file."); + console.log(""); + console.log("-------------------------- Deprecated ----------------"); + console.log(" -O0, -O1, -O2 Set the parser's optimization level. The lower"); + console.log(" the number, the less nodes it will create in the"); + console.log(" tree. This could matter for debugging, or if you"); + console.log(" want to access the individual nodes in the tree."); + console.log(" --line-numbers=TYPE Outputs filename and line numbers."); + console.log(" TYPE can be either 'comments', which will output"); + console.log(" the debug info within comments, 'mediaquery'"); + console.log(" that will output the information within a fake"); + console.log(" media query which is compatible with the SASS"); + console.log(" format, and 'all' which will do both."); + console.log(" --verbose Be verbose."); + console.log(""); + console.log("Report bugs to: http://github.com/less/less.js/issues"); + console.log("Home page: "); + } +}; + +// Exports helper functions +for (var h in lessc_helper) { exports[h] = lessc_helper[h]; } diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/parser.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/parser.js new file mode 100644 index 000000000..595d651c9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/parser.js @@ -0,0 +1,1709 @@ +var less, tree; + +// Node.js does not have a header file added which defines less +if (less === undefined) { + less = exports; + tree = require('./tree'); + less.mode = 'node'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser, + rootFilename = env && env.filename; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed around by reference. + if (!(env instanceof tree.parseEnv)) { + env = new tree.parseEnv(env); + } + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, currentFileInfo, importOptions, callback) { + var parserImports = this; + this.queue.push(path); + + var fileParsedFunc = function (e, root, fullPath) { + parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue + + var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename; + + parserImports.files[fullPath] = root; // Store the root + + if (e && !parserImports.error) { parserImports.error = e; } + + callback(e, root, importedPreviously, fullPath); + }; + + if (less.Parser.importer) { + less.Parser.importer(path, currentFileInfo, fileParsedFunc, env); + } else { + less.Parser.fileLoader(path, currentFileInfo, function(e, contents, fullPath, newFileInfo) { + if (e) {fileParsedFunc(e); return;} + + var newEnv = new tree.parseEnv(env); + + newEnv.currentFileInfo = newFileInfo; + newEnv.processImports = false; + newEnv.contents[fullPath] = contents; + + if (currentFileInfo.reference || importOptions.reference) { + newFileInfo.reference = true; + } + + if (importOptions.inline) { + fileParsedFunc(null, contents, fullPath); + } else { + new(less.Parser)(newEnv).parse(contents, function (e, root) { + fileParsedFunc(e, root, fullPath); + }); + } + }, env); + } + } + }; + + function save() { temp = chunks[j], memo = i, current = i; } + function restore() { chunks[j] = temp, i = memo, current = i; } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, length; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break; } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return tok.test(chunks[j]); + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, inputStream) { + var n = index + 1, + line = null, + column = -1; + + while (--n >= 0 && inputStream.charAt(n) !== '\n') { + column++; + } + + if (typeof index === 'number') { + line = (inputStream.slice(0, index).match(/\n/g) || "").length; + } + + return { + line: line, + column: column + }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + callLine = e.call && getLocation(e.call, input).line, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = callLine + 1; + this.callExtract = lines[callLine]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, line, lines, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + parser.imports.contents[env.currentFileInfo.filename] = input; + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': + if (!inParam) { + level++; + chunk.push(c); + break; + } + /* falls through */ + case '}': + if (!inParam) { + level--; + chunk.push(c); + chunks[++j] = chunk = []; + break; + } + /* falls through */ + case '(': + if (!inParam) { + inParam = true; + chunk.push(c); + break; + } + /* falls through */ + case ')': + if (inParam) { + inParam = false; + chunk.push(c); + break; + } + /* falls through */ + default: + chunk.push(c); + } + + i++; + } + if (level !== 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join(''); }); + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + return function (options, variables) { + options = options || {}; + var evaldRoot, + css, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, null, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + new(tree.toCSSVisitor)({compress: Boolean(options.compress)}) + .run(evaldRoot); + + if (options.sourceMap) { + evaldRoot = new tree.sourceMapOutput( + { + writeSourceMap: options.writeSourceMap, + rootNode: evaldRoot, + contentsMap: parser.imports.contents, + sourceMapFilename: options.sourceMapFilename, + sourceMapURL: options.sourceMapURL, + outputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath, + outputSourceFiles: options.outputSourceFiles, + sourceMapGenerator: options.sourceMapGenerator + }); + } + + css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.cleancss && less.mode === 'node') { + var CleanCSS = require('clean-css'); + //TODO would be nice for no advanced to be an option + return new CleanCSS({keepSpecialComments: '*', processImport: false, noRebase: true, noAdvanced: true}).minify(css); + } else if (options.compress) { + return css.replace(/(^(\s)+)|((\s)+$)/g, ""); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + var loc = getLocation(i, input); + lines = input.split('\n'); + line = loc.line + 1; + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: loc.column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + return callback(e); + } + else { + return callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + return finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') { return; } + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true, i, env.currentFileInfo); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment, false, i, env.currentFileInfo); + } + }, + + comments: function () { + var comment, comments = []; + + while(comment = $(this.comment)) { + comments.push(comment); + } + + return comments; + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true; } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { return; } + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + var color = tree.Color.fromKeyword(k); + if (color) { + return color; + } + return new(tree.Keyword)(k); + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) { return; } + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null; } + else { i += name.length; } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { + break; + } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) { + return; + } + + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + /*jshint eqnull:true */ + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) { + return; + } + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings + if (input.charAt(j) !== '`') { return; } + if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) { + error("You are using JavaScript, which has been disabled."); + } + + if (e) { $('~'); } + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")); + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return; } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i, env.currentFileInfo)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comments); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) { + return; + } + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comments); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) { return; } + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i, env.currentFileInfo); } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++; } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + // + // A CSS selector (see selector below) + // with less extensions e.g. the ability to extend and guard + // + lessSelector: function () { + return this.selector(true); + }, + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function (isLess) { + var e, elements = [], c, extend, extendList = [], when, condition; + + while ((isLess && (extend = $(this.extend))) || (isLess && (when = $(/^when/))) || (e = $(this.element))) { + if (when) { + condition = expect(this.conditions, 'expected condition'); + } else if (condition) { + error("CSS guard can only be used at the end of selector"); + } else if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e); + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { + break; + } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList, condition, i, env.currentFileInfo); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var key, val, op; + + if (! $('[')) { return; } + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[0-9]+%/) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + while (s = $(this.lessSelector)) { + selectors.push(s); + $(this.comments); + if (! $(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + $(this.comments); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) { + ruleset.debugInfo = debugInfo; + } + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, merge = false; + save(); + + if (c === '.' || c === '#' || c === '&') { return; } + + if (name = $(this.variable) || $(this.ruleProperty)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + + important = $(this.important); + if (name[name.length-1] === "+") { + merge = true; + name = name.substr(0, name.length - 1); + } + + if (value && $(this.end)) { + return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break; } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once|inline|reference)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = ($(this.entities.keyword) || $(this.entities.variable))) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null; } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break; } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break; } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + media.debugInfo = debugInfo; + } + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression, identifier; + + if (input.charAt(i) !== '@') { return; } + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) { return; } + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@host": + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + identifier = ($(/^[^{]+/) || '').trim(); + if (identifier) { + name += " " + identifier; + } + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules, i, env.currentFileInfo); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = []; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while (peek(/^,\s*(not\s*)?\(/) && $(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true; } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|<=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-'); } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = []; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + }, + ruleProperty: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/)) { + return name[1] + (name[2] || ""); + } + } + } + }; +}; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/rhino.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/rhino.js new file mode 100644 index 000000000..08f311021 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/rhino.js @@ -0,0 +1,128 @@ +/*jshint rhino:true, unused: false */ +/*global name:true, less, loadStyleSheet */ +var name; + +function error(e, filename) { + + var content = "Error : " + filename + "\n"; + + filename = e.filename || filename; + + if (e.message) { + content += e.message + "\n"; + } + + var errorline = function (e, i, classname) { + if (e.extract[i]) { + content += + String(parseInt(e.line, 10) + (i - 1)) + + ":" + e.extract[i] + "\n"; + } + }; + + if (e.stack) { + content += e.stack; + } else if (e.extract) { + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n'; + errorline(e, 0); + errorline(e, 1); + errorline(e, 2); + } + print(content); +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + input = input.replace(/^\xEF\xBB\xBF/, ''); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return error(e, sheetName); + } + try { + callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName); + } catch(e) { + error(e, sheetName); + } + }); +} + +function writeFile(filename, content) { + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); +} + +// Command line integration via Rhino +(function (args) { + var output, + compress = false, + i, + path; + + for(i = 0; i < args.length; i++) { + switch(args[i]) { + case "-x": + compress = true; + break; + default: + if (!name) { + name = args[i]; + } else if (!output) { + output = args[i]; + } else { + print("unrecognised parameters"); + print("input_file [output_file] [-x]"); + } + } + } + + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/"); + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + try { + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + error(e, name); + quit(1); + } else { + result = root.toCSS({compress: compress || false}); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); + } + }); + } + catch(e) { + error(e, name); + quit(1); + } + print("done"); +}(arguments)); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/source-map-output.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/source-map-output.js new file mode 100644 index 000000000..0eb80c5c9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/source-map-output.js @@ -0,0 +1,119 @@ +(function (tree) { + + tree.sourceMapOutput = function (options) { + this._css = []; + this._rootNode = options.rootNode; + this._writeSourceMap = options.writeSourceMap; + this._contentsMap = options.contentsMap; + this._sourceMapFilename = options.sourceMapFilename; + this._outputFilename = options.outputFilename; + this._sourceMapURL = options.sourceMapURL; + this._sourceMapBasepath = options.sourceMapBasepath; + this._sourceMapRootpath = options.sourceMapRootpath; + this._outputSourceFiles = options.outputSourceFiles; + this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator; + + if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') { + this._sourceMapRootpath += '/'; + } + + this._lineNumber = 0; + this._column = 0; + }; + + tree.sourceMapOutput.prototype.normalizeFilename = function(filename) { + if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { + filename = filename.substring(this._sourceMapBasepath.length); + if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { + filename = filename.substring(1); + } + } + return (this._sourceMapRootpath || "") + filename.replace(/\\/g, '/'); + }; + + tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { + + //ignore adding empty strings + if (!chunk) { + return; + } + + var lines, + sourceLines, + columns, + sourceColumns, + i; + + if (fileInfo) { + var inputSource = this._contentsMap[fileInfo.filename].substring(0, index); + sourceLines = inputSource.split("\n"); + sourceColumns = sourceLines[sourceLines.length-1]; + } + + lines = chunk.split("\n"); + columns = lines[lines.length-1]; + + if (fileInfo) { + if (!mapLines) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column}, + original: { line: sourceLines.length, column: sourceColumns.length}, + source: this.normalizeFilename(fileInfo.filename)}); + } else { + for(i = 0; i < lines.length; i++) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0}, + original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0}, + source: this.normalizeFilename(fileInfo.filename)}); + } + } + } + + if (lines.length === 1) { + this._column += columns.length; + } else { + this._lineNumber += lines.length - 1; + this._column = columns.length; + } + + this._css.push(chunk); + }; + + tree.sourceMapOutput.prototype.isEmpty = function() { + return this._css.length === 0; + }; + + tree.sourceMapOutput.prototype.toCSS = function(env) { + this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null }); + + if (this._outputSourceFiles) { + for(var filename in this._contentsMap) { + this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), this._contentsMap[filename]); + } + } + + this._rootNode.genCSS(env, this); + + if (this._css.length > 0) { + var sourceMapURL, + sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON()); + + if (this._sourceMapURL) { + sourceMapURL = this._sourceMapURL; + } else if (this._sourceMapFilename) { + sourceMapURL = this.normalizeFilename(this._sourceMapFilename); + } + + if (this._writeSourceMap) { + this._writeSourceMap(sourceMapContent); + } else { + sourceMapURL = "data:application/json," + encodeURIComponent(sourceMapContent); + } + + if (sourceMapURL) { + this._css.push("/*# sourceMappingURL=" + sourceMapURL + " */"); + } + } + + return this._css.join(''); + }; + +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/to-css-visitor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/to-css-visitor.js new file mode 100644 index 000000000..a9988c6fe --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/to-css-visitor.js @@ -0,0 +1,199 @@ +(function (tree) { + tree.toCSSVisitor = function(env) { + this._visitor = new tree.visitor(this); + this._env = env; + }; + + tree.toCSSVisitor.prototype = { + isReplacing: true, + run: function (root) { + return this._visitor.visit(root); + }, + + visitRule: function (ruleNode, visitArgs) { + if (ruleNode.variable) { + return []; + } + return ruleNode; + }, + + visitMixinDefinition: function (mixinNode, visitArgs) { + return []; + }, + + visitExtend: function (extendNode, visitArgs) { + return []; + }, + + visitComment: function (commentNode, visitArgs) { + if (commentNode.isSilent(this._env)) { + return []; + } + return commentNode; + }, + + visitMedia: function(mediaNode, visitArgs) { + mediaNode.accept(this._visitor); + visitArgs.visitDeeper = false; + + if (!mediaNode.rules.length) { + return []; + } + return mediaNode; + }, + + visitDirective: function(directiveNode, visitArgs) { + if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) { + return []; + } + if (directiveNode.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (this.charset) { + if (directiveNode.debugInfo) { + var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n"); + comment.debugInfo = directiveNode.debugInfo; + return this._visitor.visit(comment); + } + return []; + } + this.charset = true; + } + return directiveNode; + }, + + checkPropertiesInRoot: function(rules) { + var ruleNode; + for(var i = 0; i < rules.length; i++) { + ruleNode = rules[i]; + if (ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null}; + } + } + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var rule, rulesets = []; + if (rulesetNode.firstRoot) { + this.checkPropertiesInRoot(rulesetNode.rules); + } + if (! rulesetNode.root) { + + rulesetNode.paths = rulesetNode.paths + .filter(function(p) { + var i; + if (p[0].elements[0].combinator.value === ' ') { + p[0].elements[0].combinator = new(tree.Combinator)(''); + } + for(i = 0; i < p.length; i++) { + if (p[i].getIsReferenced() && p[i].getIsOutput()) { + return true; + } + return false; + } + }); + + // Compile rules and rulesets + for (var i = 0; i < rulesetNode.rules.length; i++) { + rule = rulesetNode.rules[i]; + + if (rule.rules) { + // visit because we are moving them out from being a child + rulesets.push(this._visitor.visit(rule)); + rulesetNode.rules.splice(i, 1); + i--; + continue; + } + } + // accept the visitor to remove rules and refactor itself + // then we can decide now whether we want it or not + if (rulesetNode.rules.length > 0) { + rulesetNode.accept(this._visitor); + } + visitArgs.visitDeeper = false; + + this._mergeRules(rulesetNode.rules); + this._removeDuplicateRules(rulesetNode.rules); + + // now decide whether we keep the ruleset + if (rulesetNode.rules.length > 0 && rulesetNode.paths.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } else { + rulesetNode.accept(this._visitor); + visitArgs.visitDeeper = false; + if (rulesetNode.firstRoot || rulesetNode.rules.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } + if (rulesets.length === 1) { + return rulesets[0]; + } + return rulesets; + }, + + _removeDuplicateRules: function(rules) { + // remove duplicates + var ruleCache = {}, + ruleList, rule, i; + for(i = rules.length - 1; i >= 0 ; i--) { + rule = rules[i]; + if (rule instanceof tree.Rule) { + if (!ruleCache[rule.name]) { + ruleCache[rule.name] = rule; + } else { + ruleList = ruleCache[rule.name]; + if (ruleList instanceof tree.Rule) { + ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)]; + } + var ruleCSS = rule.toCSS(this._env); + if (ruleList.indexOf(ruleCSS) !== -1) { + rules.splice(i, 1); + } else { + ruleList.push(ruleCSS); + } + } + } + } + }, + + _mergeRules: function (rules) { + var groups = {}, + parts, + rule, + key; + + for (var i = 0; i < rules.length; i++) { + rule = rules[i]; + + if ((rule instanceof tree.Rule) && rule.merge) { + key = [rule.name, + rule.important ? "!" : ""].join(","); + + if (!groups[key]) { + parts = groups[key] = []; + } else { + rules.splice(i--, 1); + } + + parts.push(rule); + } + } + + Object.keys(groups).map(function (k) { + parts = groups[k]; + + if (parts.length > 1) { + rule = parts[0]; + + rule.value = new (tree.Value)(parts.map(function (p) { + return p.value; + })); + } + }); + } + }; + +})(require('./tree')); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree.js new file mode 100644 index 000000000..ca9f1758d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree.js @@ -0,0 +1,78 @@ +(function (tree) { + +tree.debugInfo = function(env, ctx, lineSeperator) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) { + if (a == '\\') { + a = '\/'; + } + return '\\' + a; + }) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r; } + } + return null; +}; + +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +tree.toCSS = function (env) { + var strs = []; + this.genCSS(env, { + add: function(chunk, fileInfo, index) { + strs.push(chunk); + }, + isEmpty: function () { + return strs.length === 0; + } + }); + return strs.join(''); +}; + +tree.outputRuleset = function (env, output, rules) { + output.add((env.compress ? '{' : ' {\n')); + env.tabLevel = (env.tabLevel || 0) + 1; + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + for(var i = 0; i < rules.length; i++) { + output.add(tabRuleStr); + rules[i].genCSS(env, output); + output.add(env.compress ? '' : '\n'); + } + env.tabLevel--; + output.add(tabSetStr + "}"); +}; + +})(require('./tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/alpha.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/alpha.js new file mode 100644 index 000000000..e827fd08a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/alpha.js @@ -0,0 +1,29 @@ +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); } + return this; + }, + genCSS: function (env, output) { + output.add("alpha(opacity="); + + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + + output.add(")"); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/anonymous.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/anonymous.js new file mode 100644 index 000000000..ef2b9ecc2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/anonymous.js @@ -0,0 +1,32 @@ +(function (tree) { + +tree.Anonymous = function (string, index, currentFileInfo, mapLines) { + this.value = string.value || string; + this.index = index; + this.mapLines = mapLines; + this.currentFileInfo = currentFileInfo; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + eval: function () { return this; }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + }, + genCSS: function (env, output) { + output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/assignment.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/assignment.js new file mode 100644 index 000000000..61d22fca7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/assignment.js @@ -0,0 +1,29 @@ +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add(this.key + '='); + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/call.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/call.js new file mode 100644 index 000000000..6d262b819 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/call.js @@ -0,0 +1,70 @@ +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + /*jshint eqnull:true */ + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + return new tree.Call(this.name, args, this.index, this.currentFileInfo); + }, + + genCSS: function (env, output) { + output.add(this.name + "(", this.currentFileInfo, this.index); + + for(var i = 0; i < this.args.length; i++) { + this.args[i].genCSS(env, output); + if (i + 1 < this.args.length) { + output.add(", "); + } + } + + output.add(")"); + }, + + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/color.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/color.js new file mode 100644 index 000000000..2e45db11d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/color.js @@ -0,0 +1,178 @@ +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; + +var transparentKeyword = "transparent"; + +tree.Color.prototype = { + type: "Color", + eval: function () { return this; }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + if (this.alpha < 1.0) { + if (this.alpha === 0 && this.isTransparentKeyword) { + return transparentKeyword; + } + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.toRGB(); + + if (compress) { + var splitcolor = color.split(''); + + // Convert color to short format + if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) { + color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5]; + } + } + + return color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toRGB: function () { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + +tree.Color.fromKeyword = function(keyword) { + if (tree.colors.hasOwnProperty(keyword)) { + // detect named color + return new(tree.Color)(tree.colors[keyword].slice(1)); + } + if (keyword === transparentKeyword) { + var transparent = new(tree.Color)([0, 0, 0], 0); + transparent.isTransparentKeyword = true; + return transparent; + } +}; + + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/comment.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/comment.js new file mode 100644 index 000000000..c39606e09 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/comment.js @@ -0,0 +1,28 @@ +(function (tree) { + +tree.Comment = function (value, silent, index, currentFileInfo) { + this.value = value; + this.silent = !!silent; + this.currentFileInfo = currentFileInfo; +}; +tree.Comment.prototype = { + type: "Comment", + genCSS: function (env, output) { + if (this.debugInfo) { + output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index); + } + output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n + }, + toCSS: tree.toCSS, + isSilent: function(env) { + var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced), + isCompressed = env.compress && !this.value.match(/^\/\*!/); + return this.silent || isReference || isCompressed; + }, + eval: function () { return this; }, + markReferenced: function () { + this.isReferenced = true; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/condition.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/condition.js new file mode 100644 index 000000000..56d221efb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/condition.js @@ -0,0 +1,49 @@ +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<' || op === '<='; + case 0: return op === '=' || op === '>=' || op === '=<' || op === '<='; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/dimension.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/dimension.js new file mode 100644 index 000000000..c64cd89ac --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/dimension.js @@ -0,0 +1,313 @@ +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + genCSS: function (env, output) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && this.unit.isLength()) { + output.add(strValue); + return; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + output.add(strValue); + this.unit.genCSS(env, output); + }, + toCSS: tree.toCSS, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + /*jshint noempty:false */ + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, targetUnit, derivedConversions = {}, applyUnit; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + applyUnit = function (atomicUnit, denominator) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(applyUnit); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + genCSS: function (env, output) { + if (this.numerator.length >= 1) { + output.add(this.numerator[0]); + } else + if (this.denominator.length >= 1) { + output.add(this.denominator[0]); + } else + if ((!env || !env.strictUnits) && this.backupUnit) { + output.add(this.backupUnit); + } + }, + toCSS: tree.toCSS, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isLength: function () { + return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/)); + }, + + isEmpty: function () { + return this.numerator.length === 0 && this.denominator.length === 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length === 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, result = {}, mapUnit; + + mapUnit = function (atomicUnit) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }; + + for (var groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(mapUnit); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/directive.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/directive.js new file mode 100644 index 000000000..64082593b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/directive.js @@ -0,0 +1,60 @@ +(function (tree) { + +tree.Directive = function (name, value, index, currentFileInfo) { + this.name = name; + + if (Array.isArray(value)) { + this.rules = [new(tree.Ruleset)([], value)]; + this.rules[0].allowImports = true; + } else { + this.value = value; + } + this.currentFileInfo = currentFileInfo; + +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.rules = visitor.visit(this.rules); + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name, this.currentFileInfo, this.index); + if (this.rules) { + tree.outputRuleset(env, output, this.rules); + } else { + output.add(' '); + this.value.genCSS(env, output); + output.add(';'); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var evaldDirective = this; + if (this.rules) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo); + evaldDirective.rules = [this.rules[0].eval(env)]; + evaldDirective.rules[0].root = true; + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + markReferenced: function () { + var i, rules; + this.isReferenced = true; + if (this.rules) { + rules = this.rules[0].rules; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + } + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/element.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/element.js new file mode 100644 index 000000000..1c25aeecc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/element.js @@ -0,0 +1,104 @@ +(function (tree) { + +tree.Element = function (combinator, value, index, currentFileInfo) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index, + this.currentFileInfo); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env), this.currentFileInfo, this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value === '' && this.combinator.value.charAt(0) === '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + _outputMap: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : ' + ', + '~' : ' ~ ', + '>' : ' > ', + '|' : '|' + }, + _outputMapCompressed: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : '+', + '~' : '~', + '>' : '>', + '|' : '|' + }, + genCSS: function (env, output) { + output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/expression.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/expression.js new file mode 100644 index 000000000..239692975 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/expression.js @@ -0,0 +1,52 @@ +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + genCSS: function (env, output) { + for(var i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add(" "); + } + } + }, + toCSS: tree.toCSS, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/extend.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/extend.js new file mode 100644 index 000000000..5f7a4687b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/extend.js @@ -0,0 +1,50 @@ +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i, + selectorElements; + + for(i = 0; i < selectors.length; i++) { + selectorElements = selectors[i].elements; + // duplicate the logic in genCSS function inside the selector node. + // future TODO - move both logics into the selector joiner visitor + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + selectorElements[0].combinator.value = ' '; + } + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/import.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/import.js new file mode 100644 index 000000000..cf8ac02bc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/import.js @@ -0,0 +1,115 @@ +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined || this.options.inline) { + this.css = !this.options.less || this.options.inline; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + if (!this.options.inline) { + this.root = visitor.visit(this.root); + } + }, + genCSS: function (env, output) { + if (this.css) { + output.add("@import ", this.currentFileInfo, this.index); + this.path.genCSS(env, output); + if (this.features) { + output.add(" "); + this.features.genCSS(env, output); + } + output.add(';'); + } + }, + toCSS: tree.toCSS, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + + if (!(path instanceof tree.URL)) { + if (rootpath) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + path.value = env.normalizePath(path.value); + } + + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.options.inline) { + //todo needs to reference css file not import + var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true); + return this.features ? new(tree.Media)([contents], this.features.value) : [contents]; + } else if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/javascript.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/javascript.js new file mode 100644 index 000000000..dc7910c48 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/javascript.js @@ -0,0 +1,53 @@ +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + /*jshint loopfunc:true */ + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/keyword.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/keyword.js new file mode 100644 index 000000000..8cfbb09c5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/keyword.js @@ -0,0 +1,23 @@ +(function (tree) { + +tree.Keyword = function (value) { this.value = value; }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/media.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/media.js new file mode 100644 index 000000000..c5cdbd781 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/media.js @@ -0,0 +1,148 @@ +(function (tree) { + +tree.Media = function (value, features, index, currentFileInfo) { + this.index = index; + this.currentFileInfo = currentFileInfo; + + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.rules = [new(tree.Ruleset)(selectors, value)]; + this.rules[0].allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.rules = visitor.visit(this.rules); + }, + genCSS: function (env, output) { + output.add('@media ', this.currentFileInfo, this.index); + this.features.genCSS(env, output); + tree.outputRuleset(env, output, this.rules); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], [], this.index, this.currentFileInfo); + if(this.debugInfo) { + this.rules[0].debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.rules[0]); + media.rules = [this.rules[0].eval(env)]; + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env); + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', this.index, this.currentFileInfo); + return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)]; + }, + markReferenced: function () { + var i, rules = this.rules[0].rules; + this.isReferenced = true; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])]; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/mixin.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/mixin.js new file mode 100644 index 000000000..ff168fc1f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/mixin.js @@ -0,0 +1,254 @@ +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + if (!(mixin instanceof tree.mixin.Definition)) { + mixin = new tree.mixin.Definition("", [], mixin.rules, null, false); + mixin.originalRuleset = mixins[m].originalRuleset || mixins[m]; + } + //if (this.important) { + // isImportant = env.isImportant; + // env.isImportant = true; + //} + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + //if (this.important) { + // env.isImportant = isImportant; + //} + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + if (!this.currentFileInfo || !this.currentFileInfo.reference) { + for (i = 0; i < rules.length; i++) { + rule = rules[i]; + if (rule.markReferenced) { + rule.markReferenced(); + } + } + } + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1; } + else { return count; } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + /*jshint boss:true */ + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) { continue; } + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + rules, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules); + ruleset.originalRuleset = this; + ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames))); + if (important) { + ruleset = this.parent.makeImportant.apply(ruleset); + } + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables + .concat(this.frames) // the parent namespace/mixin frames + .concat(env.frames)))) { // the current environment frames + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (! this.variadic) { + if (argsLength < this.required) { return false; } + if (argsLength > this.params.length) { return false; } + } else { + if (argsLength < (this.required - 1)) { return false; } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/negative.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/negative.js new file mode 100644 index 000000000..12dbcc63c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/negative.js @@ -0,0 +1,24 @@ +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('-'); + this.value.genCSS(env, output); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/operation.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/operation.js new file mode 100644 index 000000000..ec806e29d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/operation.js @@ -0,0 +1,60 @@ +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + genCSS: function (env, output) { + this.operands[0].genCSS(env, output); + if (this.isSpaced) { + output.add(" "); + } + output.add(this.op); + if (this.isSpaced) { + output.add(" "); + } + this.operands[1].genCSS(env, output); + }, + toCSS: tree.toCSS +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/paren.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/paren.js new file mode 100644 index 000000000..e27b8d668 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/paren.js @@ -0,0 +1,23 @@ + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('('); + this.value.genCSS(env, output); + output.add(')'); + }, + toCSS: tree.toCSS, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/quoted.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/quoted.js new file mode 100644 index 000000000..131bfad90 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/quoted.js @@ -0,0 +1,48 @@ +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + genCSS: function (env, output) { + if (!this.escaped) { + output.add(this.quote, this.currentFileInfo, this.index); + } + output.add(this.value); + if (!this.escaped) { + output.add(this.quote); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/rule.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/rule.js new file mode 100644 index 000000000..20562094d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/rule.js @@ -0,0 +1,60 @@ +(function (tree) { + +tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (name.charAt(0) === '@'); +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index); + try { + this.value.genCSS(env, output); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index); + }, + toCSS: tree.toCSS, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.merge, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.merge, + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/ruleset.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/ruleset.js new file mode 100644 index 000000000..a89dfb001 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/ruleset.js @@ -0,0 +1,462 @@ +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + if (this.paths) { + for(var i = 0; i < this.paths.length; i++) { + this.paths[i] = visitor.visit(this.paths[i]); + } + } else { + this.selectors = visitor.visit(this.selectors); + } + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env); }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + var rule; + var i; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + /*jshint loopfunc:true */ + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (i = 0; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + matchCondition: function (args, env) { + var lastSelector = this.selectors[this.selectors.length-1]; + if (lastSelector.condition && + !lastSelector.condition.eval( + new(tree.evalEnv)(env, + env.frames))) { + return false; + } + return true; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables; } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key]; } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > match) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(match)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + genCSS: function (env, output) { + var i, j, + ruleNodes = [], + rulesetNodes = [], + debugInfo, // Line number debugging + rule, + firstRuleset = true, + path; + + env.tabLevel = (env.tabLevel || 0); + + if (!this.root) { + env.tabLevel++; + } + + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + + for (i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + if (rule.rules || (rule instanceof tree.Media) || rule instanceof tree.Directive || (this.root && rule instanceof tree.Comment)) { + rulesetNodes.push(rule); + } else { + ruleNodes.push(rule); + } + } + + // If this is the root node, we don't render + // a selector, or {}. + if (!this.root) { + debugInfo = tree.debugInfo(env, this, tabSetStr); + + if (debugInfo) { + output.add(debugInfo); + output.add(tabSetStr); + } + + for(i = 0; i < this.paths.length; i++) { + path = this.paths[i]; + env.firstSelector = true; + for(j = 0; j < path.length; j++) { + path[j].genCSS(env, output); + env.firstSelector = false; + } + if (i + 1 < this.paths.length) { + output.add(env.compress ? ',' : (',\n' + tabSetStr)); + } + } + + output.add((env.compress ? '{' : ' {\n') + tabRuleStr); + } + + // Compile rules and rulesets + for (i = 0; i < ruleNodes.length; i++) { + rule = ruleNodes[i]; + + // @page{ directive ends up with root elements inside it, a mix of rules and rulesets + // In this instance we do not know whether it is the last property + if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) { + env.lastRule = true; + } + + if (rule.genCSS) { + rule.genCSS(env, output); + } else if (rule.value) { + output.add(rule.value.toString()); + } + + if (!env.lastRule) { + output.add(env.compress ? '' : ('\n' + tabRuleStr)); + } else { + env.lastRule = false; + } + } + + if (!this.root) { + output.add((env.compress ? '}' : '\n' + tabSetStr + '}')); + env.tabLevel--; + } + + for (i = 0; i < rulesetNodes.length; i++) { + if (ruleNodes.length && firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + if (!firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + firstRuleset = false; + rulesetNodes[i].genCSS(env, output); + } + + if (!output.isEmpty() && !env.compress && this.firstRoot) { + output.add('\n'); + } + }, + + toCSS: tree.toCSS, + + markReferenced: function () { + for (var s = 0; s < this.selectors.length; s++) { + this.selectors[s].markReferenced(); + } + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for (i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for (j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length === 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0, el.index, el.currentFileInfo)); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for (k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = selector.createDerived([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for (i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length === 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for (i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/selector.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/selector.js new file mode 100644 index 000000000..02e126752 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/selector.js @@ -0,0 +1,82 @@ +(function (tree) { + +tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) { + this.elements = elements; + this.extendList = extendList || []; + this.condition = condition; + this.currentFileInfo = currentFileInfo || {}; + this.isReferenced = isReferenced; + if (!condition) { + this.evaldCondition = true; + } +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList); + this.condition = visitor.visit(this.condition); + }, + createDerived: function(elements, extendList, evaldCondition) { + /*jshint eqnull:true */ + evaldCondition = evaldCondition != null ? evaldCondition : this.evaldCondition; + var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced); + newSelector.evaldCondition = evaldCondition; + return newSelector; + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return 0; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return 0; + } + } + } + return max; // return number of matched selectors + }, + eval: function (env) { + var evaldCondition = this.condition && this.condition.eval(env); + + return this.createDerived(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + }), evaldCondition); + }, + genCSS: function (env, output) { + var i, element; + if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") { + output.add(' ', this.currentFileInfo, this.index); + } + if (!this._css) { + //TODO caching? speed comparison? + for(i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(env, output); + } + } + }, + toCSS: tree.toCSS, + markReferenced: function () { + this.isReferenced = true; + }, + getIsReferenced: function() { + return !this.currentFileInfo.reference || this.isReferenced; + }, + getIsOutput: function() { + return this.evaldCondition; + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/unicode-descriptor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/unicode-descriptor.js new file mode 100644 index 000000000..7bf98ea56 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/unicode-descriptor.js @@ -0,0 +1,15 @@ +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + eval: function () { return this; } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/url.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/url.js new file mode 100644 index 000000000..79c2879ce --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/url.js @@ -0,0 +1,36 @@ +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add("url("); + this.value.genCSS(env, output); + output.add(")"); + }, + toCSS: tree.toCSS, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + val.value = ctx.normalizePath(val.value); + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/value.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/value.js new file mode 100644 index 000000000..93630c3c0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/value.js @@ -0,0 +1,32 @@ +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + genCSS: function (env, output) { + var i; + for(i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i+1 < this.value.length) { + output.add((env && env.compress) ? ',' : ', '); + } + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/variable.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/variable.js new file mode 100644 index 000000000..8f1469323 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/tree/variable.js @@ -0,0 +1,43 @@ +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { + this.name = name; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') === 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); diff --git a/node_modules/grunt-contrib-less/node_modules/less/lib/less/visitor.js b/node_modules/grunt-contrib-less/node_modules/less/lib/less/visitor.js new file mode 100644 index 000000000..52f734f1a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/lib/less/visitor.js @@ -0,0 +1,69 @@ +(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + evald = this.flatten(evald); + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + }, + doAccept: function (node) { + node.accept(this); + }, + flatten: function(arr, master) { + return arr.reduce(this.flattenReduce.bind(this), master || []); + }, + flattenReduce: function(sum, element) { + if (element instanceof Array) { + sum = this.flatten(element, sum); + } else { + sum.push(element); + } + return sum; + } + }; + +})(require('./tree')); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/.bin/cleancss b/node_modules/grunt-contrib-less/node_modules/less/node_modules/.bin/cleancss new file mode 120000 index 000000000..2a3439ebe --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/.bin/cleancss @@ -0,0 +1 @@ +../clean-css/bin/cleancss \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/History.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/History.md new file mode 100644 index 000000000..23dbe56fd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/History.md @@ -0,0 +1,346 @@ +[2.0.2 / 2013-11-18](https://github.com/GoalSmashers/clean-css/compare/v2.0.1...v2.0.2) +================== + +* Fixed issue [#177](https://github.com/GoalSmashers/clean-css/issues/177) - process broken content correctly. + +[2.0.1 / 2013-11-14](https://github.com/GoalSmashers/clean-css/compare/v2.0.0...v2.0.1) +================== + +* Fixed issue [#176](https://github.com/GoalSmashers/clean-css/issues/176) - hangs on `undefined` keyword. + +[2.0.0 / 2013-11-04](https://github.com/GoalSmashers/clean-css/compare/v1.1.7...v2.0.0) +================== + +* Adds simplified and more advanced text escaping / restoring via `EscapeStore` class. +* Adds simplified and much faster empty elements removal. +* Adds missing `@import` processing to our benchmark (run via `npm run bench`). +* Adds CSS tokenizer which will make it possible to optimize content by reordering and/or merging selectors. +* Adds basic optimizer removing duplicate selectors from a list. +* Adds merging duplicate properties within a single selector's body. +* Adds merging adjacent selectors within a scope (single and multiple ones). +* Changes behavior of `--keep-line-breaks`/`keepBreaks` option to keep breaks after trailing braces only. +* Makes all multiple selectors ordered alphabetically (aids merging). +* Adds property overriding so more coarse properties override more granular ones. +* Adds reducing non-adjacent selectors. +* Adds `--skip-advanced`/`noAdvanced` switch to disable advanced optimizations. +* Adds reducing non-adjacent selectors when overridden by more complex selectors. +* Fixed issue [#138](https://github.com/GoalSmashers/clean-css/issues/138) - makes CleanCSS interface OO. +* Fixed issue [#139](https://github.com/GoalSmashers/clean-css/issues/138) - consistent error & warning handling. +* Fixed issue [#145](https://github.com/GoalSmashers/clean-css/issues/145) - debug mode in library too. +* Fixed issue [#157](https://github.com/GoalSmashers/clean-css/issues/157) - gets rid of `removeEmpty` option. +* Fixed issue [#159](https://github.com/GoalSmashers/clean-css/issues/159) - escaped quotes inside content. +* Fixed issue [#162](https://github.com/GoalSmashers/clean-css/issues/162) - strip quotes from Base64 encoded URLs. +* Fixed issue [#166](https://github.com/GoalSmashers/clean-css/issues/166) - `debug` formatting in CLI +* Fixed issue [#167](https://github.com/GoalSmashers/clean-css/issues/167) - `background:transparent` minification. + +[1.1.7 / 2013-10-28](https://github.com/GoalSmashers/clean-css/compare/v1.1.6...v1.1.7) +================== + +* Fixed issue [#156](https://github.com/GoalSmashers/clean-css/issues/156) - `@import`s inside comments. + +[1.1.6 / 2013-10-26](https://github.com/GoalSmashers/clean-css/compare/v1.1.5...v1.1.6) +================== + +* Fixed issue [#155](https://github.com/GoalSmashers/clean-css/issues/155) - broken irregular CSS content. + +[1.1.5 / 2013-10-24](https://github.com/GoalSmashers/clean-css/compare/v1.1.4...v1.1.5) +================== + +* Fixed issue [#153](https://github.com/GoalSmashers/clean-css/issues/153) - keepSpecialComments 0/1 as a string. + +[1.1.4 / 2013-10-23](https://github.com/GoalSmashers/clean-css/compare/v1.1.3...v1.1.4) +================== + +* Fixed issue [#152](https://github.com/GoalSmashers/clean-css/issues/152) - adds an option to disable rebasing. + +[1.1.3 / 2013-10-04](https://github.com/GoalSmashers/clean-css/compare/v1.1.2...v1.1.3) +================== + +* Fixed issue [#150](https://github.com/GoalSmashers/clean-css/issues/150) - minifying `background:none`. + +[1.1.2 / 2013-09-29](https://github.com/GoalSmashers/clean-css/compare/v1.1.1...v1.1.2) +================== + +* Fixed issue [#149](https://github.com/GoalSmashers/clean-css/issues/149) - shorthand font property. + +[1.1.1 / 2013-09-07](https://github.com/GoalSmashers/clean-css/compare/v1.1.0...v1.1.1) +================== + +* Fixed issue [#144](https://github.com/GoalSmashers/clean-css/issues/144) - skip URLs rebasing by default. + +[1.1.0 / 2013-09-06](https://github.com/GoalSmashers/clean-css/compare/v1.0.12...v1.1.0) +================== + +* Renamed lib's `debug` option to `benchmark` when doing per-minification benchmarking. +* Added simplified comments processing & imports. +* Fixed issue [#43](https://github.com/GoalSmashers/clean-css/issues/43) - `--debug` switch for minification stats. +* Fixed issue [#65](https://github.com/GoalSmashers/clean-css/issues/65) - full color name / hex shortening. +* Fixed issue [#84](https://github.com/GoalSmashers/clean-css/issues/84) - support for `@import` with media queries. +* Fixed issue [#124](https://github.com/GoalSmashers/clean-css/issues/124) - raise error on broken imports. +* Fixed issue [#126](https://github.com/GoalSmashers/clean-css/issues/126) - proper CSS expressions handling. +* Fixed issue [#129](https://github.com/GoalSmashers/clean-css/issues/129) - rebasing imported URLs. +* Fixed issue [#130](https://github.com/GoalSmashers/clean-css/issues/130) - better code modularity. +* Fixed issue [#135](https://github.com/GoalSmashers/clean-css/issues/135) - require node.js 0.8+. + +[1.0.12 / 2013-07-19](https://github.com/GoalSmashers/clean-css/compare/v1.0.11...v1.0.12) +=================== + +* Fixed issue [#121](https://github.com/GoalSmashers/clean-css/issues/121) - ability to skip `@import` processing. + +[1.0.11 / 2013-07-08](https://github.com/GoalSmashers/clean-css/compare/v1.0.10...v1.0.11) +=================== + +* Fixed issue [#117](https://github.com/GoalSmashers/clean-css/issues/117) - line break escaping in comments. + +[1.0.10 / 2013-06-13](https://github.com/GoalSmashers/clean-css/compare/v1.0.9...v1.0.10) +=================== + +* Fixed issue [#114](https://github.com/GoalSmashers/clean-css/issues/114) - comments in imported stylesheets. + +[1.0.9 / 2013-06-11](https://github.com/GoalSmashers/clean-css/compare/v1.0.8...v1.0.9) +================== + +* Fixed issue [#113](https://github.com/GoalSmashers/clean-css/issues/113) - `@import` in comments. + +[1.0.8 / 2013-06-10](https://github.com/GoalSmashers/clean-css/compare/v1.0.7...v1.0.8) +================== + +* Fixed issue [#112](https://github.com/GoalSmashers/clean-css/issues/112) - reducing `box-shadow` zeros. + +[1.0.7 / 2013-06-05](https://github.com/GoalSmashers/clean-css/compare/v1.0.6...v1.0.7) +================== + +* Support for `@import` URLs starting with `//`. + By [@petetak](https://github.com/petetak). + +[1.0.6 / 2013-06-04](https://github.com/GoalSmashers/clean-css/compare/v1.0.5...v1.0.6) +================== + +* Fixed issue [#110](https://github.com/GoalSmashers/clean-css/issues/110) - data URIs in URLs. + +[1.0.5 / 2013-05-26](https://github.com/GoalSmashers/clean-css/compare/v1.0.4...v1.0.5) +================== + +* Fixed issue [#107](https://github.com/GoalSmashers/clean-css/issues/107) - data URIs in imported stylesheets. + +1.0.4 / 2013-05-23 +================== + +* Rewrite relative URLs in imported stylesheets. + By [@bluej100](https://github.com/bluej100). + +1.0.3 / 2013-05-20 +================== + +* Support alternative `@import` syntax with file name not wrapped inside `url()` statement. + By [@bluej100](https://github.com/bluej100). + +1.0.2 / 2013-04-29 +================== + +* Fixed issue [#97](https://github.com/GoalSmashers/clean-css/issues/97) - `--remove-empty` & FontAwesome. + +1.0.1 / 2013-04-08 +================== + +* Do not pick up `bench` and `test` while building `npm` package. + By [@sindresorhus](https://https://github.com/sindresorhus). + +1.0.0 / 2013-03-30 +================== + +* Fixed issue [#2](https://github.com/GoalSmashers/clean-css/issues/2) - resolving `@import` rules. +* Fixed issue [#44](https://github.com/GoalSmashers/clean-css/issues/44) - examples in `--help`. +* Fixed issue [#46](https://github.com/GoalSmashers/clean-css/issues/46) - preserving special characters in URLs and attributes. +* Fixed issue [#80](https://github.com/GoalSmashers/clean-css/issues/80) - quotation in multi line strings. +* Fixed issue [#83](https://github.com/GoalSmashers/clean-css/issues/83) - HSL to hex color conversions. +* Fixed issue [#86](https://github.com/GoalSmashers/clean-css/issues/86) - broken `@charset` replacing. +* Fixed issue [#88](https://github.com/GoalSmashers/clean-css/issues/88) - removes space in `! important`. +* Fixed issue [#92](https://github.com/GoalSmashers/clean-css/issues/92) - uppercase hex to short versions. + +0.10.2 / 2013-03-19 +=================== + +* Fixed issue [#79](https://github.com/GoalSmashers/clean-css/issues/79) - node.js 0.10.x compatibility. + +0.10.1 / 2013-02-14 +=================== + +* Fixed issue [#66](https://github.com/GoalSmashers/clean-css/issues/66) - line breaks without extra spaces should + be handled correctly. + +0.10.0 / 2013-02-09 +=================== + +* Switched from [optimist](https://github.com/substack/node-optimist) to + [commander](https://github.com/visionmedia/commander.js) for CLI processing. +* Changed long options from `--removeempty` to `--remove-empty` and from `--keeplinebreaks` to `--keep-line-breaks`. +* Fixed performance issue with replacing multiple `@charset` declarations and issue + with line break after `@charset` when using `keepLineBreaks` option. By [@rrjaime](https://github.com/rrjamie). +* Removed Makefile in favor to `npm run` commands (e.g. `make check` -> `npm run check`). +* Fixed issue [#47](https://github.com/GoalSmashers/clean-css/issues/47) - commandline issues on Windows. +* Fixed issue [#49](https://github.com/GoalSmashers/clean-css/issues/49) - remove empty selectors from media query. +* Fixed issue [#52](https://github.com/GoalSmashers/clean-css/issues/52) - strip fraction zeros if not needed. +* Fixed issue [#58](https://github.com/GoalSmashers/clean-css/issues/58) - remove colon where possible. +* Fixed issue [#59](https://github.com/GoalSmashers/clean-css/issues/59) - content property handling. + +0.9.1 / 2012-12-19 +================== + +* Fixed issue [#37](https://github.com/GoalSmashers/clean-css/issues/37) - converting + `white` and other colors in class names (reported by [@malgorithms](https://github.com/malgorithms)). + +0.9.0 / 2012-12-15 +================== + +* Added stripping quotation from font names (if possible). +* Added stripping quotation from `@keyframes` declaration, `animation` and + `animation-name` property. +* Added stripping quotations from attributes' value (e.g. `[data-target='x']`). +* Added better hex->name and name->hex color shortening. +* Added `font: normal` and `font: bold` shortening the same way as `font-weight` is. +* Refactored shorthand selectors and added `border-radius`, `border-style` + and `border-color` shortening. +* Added `margin`, `padding` and `border-width` shortening. +* Added removing line break after commas. +* Fixed removing whitespace inside media query definition. +* Added removing line breaks after a comma, so all declarations are one-liners now. +* Speed optimizations (~10% despite many new features). +* Added [JSHint](https://github.com/jshint/jshint/) validation rules via `make check`. + +0.8.3 / 2012-11-29 +================== + +* Fixed HSL/HSLA colors processing. + +0.8.2 / 2012-10-31 +================== + +* Fixed shortening hex colors and their relation to hashes in URLs. +* Cleanup by [@XhmikosR](https://github.com/XhmikosR). + +0.8.1 / 2012-10-28 +================== + +* Added better zeros processing for `rect(...)` syntax (clip property). + +0.8.0 / 2012-10-21 +================== + +* Added removing URLs quotation if possible. +* Rewrote breaks processing. +* Added `keepBreaks`/`-b` option to keep line breaks in the minimized file. +* Reformatted [lib/clean.js](/lib/clean.js) so it's easier to follow the rules. +* Minimized test data is now minimized with line breaks so it's easier to + compare the changes line by line. + +0.7.0 / 2012-10-14 +================== + +* Added stripping special comments to CLI (`--s0` and `--s1` options). +* Added stripping special comments to programmatic interface + (`keepSpecialComments` option). + +0.6.0 / 2012-08-05 +================== + +* Full Windows support with tests (./test.bat). + +0.5.0 / 2012-08-02 +================== + +* Made path to vows local. +* Explicit node.js 0.6 requirement. + +0.4.2 / 2012-06-28 +================== + +* Updated binary `-v` option (version). +* Updated binary to output help when no options given (but not in piped mode). +* Added binary tests. + +0.4.1 / 2012-06-10 +================== + +* Fixed stateless mode where calling `CleanCSS#process` directly was giving + errors (reported by [@facelessuser](https://github.com/facelessuser)). + +0.4.0 / 2012-06-04 +================== + +* Speed improvements up to 4x thanks to the rewrite of comments and CSS' content + processing. +* Stripping empty CSS tags is now optional (see [bin/cleancss](/bin/cleancss) for details). +* Improved debugging mode (see [test/bench.js](/test/bench.js)) +* Added `make bench` for a one-pass benchmark. + +0.3.3 / 2012-05-27 +================== + +* Fixed tests, [package.json](/package.json) for development, and regex + for removing empty declarations (thanks to [@vvo](https://github.com/vvo)). + +0.3.2 / 2012-01-17 +================== + +* Fixed output method under node.js 0.6 which incorrectly tried to close + `process.stdout`. + +0.3.1 / 2011-12-16 +================== + +* Fixed cleaning up `0 0 0 0` expressions. + +0.3.0 / 2011-11-29 +================== + +* Clean-css requires node.js 0.4.0+ to run. +* Removed node.js's 0.2.x 'sys' package dependency + (thanks to [@jmalonzo](https://github.com/jmalonzo) for a patch). + +0.2.6 / 2011-11-27 +================== + +* Fixed expanding `+` signs in `calc()` when mixed up with adjacent `+` selector. + +0.2.5 / 2011-11-27 +================== + +* Fixed issue with cleaning up spaces inside `calc`/`-moz-calc` declarations + (thanks to [@cvan](https://github.com/cvan) for reporting it). +* Fixed converting `#f00` to `red` in borders and gradients. + +0.2.4 / 2011-05-25 +================== + +* Fixed problem with expanding `none` to `0` in partial/full background + declarations. +* Fixed including clean-css library from binary (global to local). + +0.2.3 / 2011-04-18 +================== + +* Fixed problem with optimizing IE filters. + +0.2.2 / 2011-04-17 +================== + +* Fixed problem with space before color in `border` property. + +0.2.1 / 2011-03-19 +================== + +* Added stripping space before `!important` keyword. +* Updated repository location and author information in [package.json](/package.json). + +0.2.0 / 2011-03-02 +================== + +* Added options parsing via optimist. +* Changed code inclusion (thus the version bump). + +0.1.0 / 2011-02-27 +================== + +* First version of clean-css library. +* Implemented all basic CSS transformations. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/LICENSE new file mode 100644 index 000000000..1509aa3d0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011-2013 GoalSmashers.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/README.md new file mode 100644 index 000000000..8b28e5c3e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/README.md @@ -0,0 +1,187 @@ +[![NPM version](https://badge.fury.io/js/clean-css.png)](https://badge.fury.io/js/clean-css) +[![Build Status](https://secure.travis-ci.org/GoalSmashers/clean-css.png)](https://travis-ci.org/GoalSmashers/clean-css) +[![Dependency Status](https://david-dm.org/GoalSmashers/clean-css.png)](https://david-dm.org/GoalSmashers/clean-css) +[![devDependency Status](https://david-dm.org/GoalSmashers/clean-css/dev-status.png)](https://david-dm.org/GoalSmashers/clean-css#info=devDependencies) + +## What is clean-css? + +Clean-css is a fast and efficient [node.js](http://nodejs.org/) library for minifying CSS files. + +According to [tests](https://github.com/GoalSmashers/css-minification-benchmark) it is one of the best available. + + +## Usage + +### What are the requirements? + +``` +node.js 0.8.0+ (tested on CentOS, Ubuntu, OS X 10.6+, and Windows 7+) +``` + +### How to install clean-css? + +``` +npm install clean-css +``` + +### How to upgrade clean-css from 1.x to 2.x? + +#### Command-line interface (CLI) + +``` +npm update clean-css +``` + +or point `package.json` to version 2.x. That's it! + +#### Node.js module + +Update `clean-css` as for CLI above. +Then change your JavaScript code from: + +```js +var minimized = CleanCSS.process(source, options); +``` + +into + +```js +var minimized = new CleanCSS(options).minify(source); +``` + +And you are done. + +### How to use clean-css CLI? + +Clean-css accepts the following command line arguments (please make sure +you use `` as the very last argument to avoid potential issues): + +``` +cleancss [options] + +-h, --help Output usage information +-v, --version Output the version number +-b, --keep-line-breaks Keep line breaks +--s0 Remove all special comments, i.e. /*! comment */ +--s1 Remove all special comments but the first one +-r, --root [root-path] A root path to which resolve absolute @import rules + and rebase relative URLs +-o, --output [output-file] Use [output-file] as output instead of STDOUT +-s, --skip-import Disable @import processing +--skip-rebase Disable URLs rebasing +--skip-advanced Disable advanced optimizations - selector & property merging, + reduction, etc. +--selectors-merge-mode [ie8|*] Use `ie8` for compatibility mode, `*` for merge all (default) +-d, --debug Shows debug information (minification time & compression efficiency) +``` + +#### Examples: + +To minify a **public.css** file into **public-min.css** do: + +``` +cleancss -o public-min.css public.css +``` + +To minify the same **public.css** into the standard output skip the `-o` parameter: + +``` +cleancss public.css +``` + +More likely you would like to concatenate a couple of files. +If you are on a Unix-like system: + +```bash +cat one.css two.css three.css | cleancss -o merged-and-minified.css +``` + +On Windows: + +```bat +type one.css two.css three.css | cleancss -o merged-and-minified.css +``` + +Or even gzip the result at once: + +```bash +cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz +``` + +### How to use clean-css programmatically? + +```js +var CleanCSS = require('clean-css'); +var source = 'a{font-weight:bold;}'; +var minimized = new CleanCSS().minify(source); +``` + +CleanCSS constructor accepts a hash as a parameter, i.e., +`new CleanCSS(options).minify(source)` with the following options available: + +* `keepSpecialComments` - `*` for keeping all (default), `1` for keeping first one only, `0` for removing all +* `keepBreaks` - whether to keep line breaks (default is false) +* `benchmark` - turns on benchmarking mode measuring time spent on cleaning up + (run `npm run bench` to see example) +* `root` - path to resolve absolute `@import` rules and rebase relative URLs +* `relativeTo` - path with which to resolve relative `@import` rules and URLs +* `processImport` - whether to process `@import` rules +* `noRebase` - whether to skip URLs rebasing +* `noAdvanced` - set to true to disable advanced optimizations - selector & property merging, reduction, etc. +* `selectorsMergeMode` - `ie8` for IE8 compatibility mode, `*` for merging all (default) +* `debug` - set to true to get minification statistics under `stats` property (see `test/custom-test.js` for examples) + +### What are the clean-css' dev commands? + +First clone the source, then run: + +* `npm run bench` for clean-css benchmarks (see [test/bench.js](https://github.com/GoalSmashers/clean-css/blob/master/test/bench.js) for details) +* `npm run check` to check JS sources with [JSHint](https://github.com/jshint/jshint/) +* `npm test` for the test suite + +## Tips & Tricks + +### How to preserve a comment block? + +Use the `/*!` notation instead of the standard one `/*`: + +```css +/*! + Important comments included in minified output. +*/ +``` + +### How to rebase relative image URLs + +Clean-css will handle it automatically for you (since version 1.1) in the following cases: + +* When using the CLI: + 1. Use an output path via `-o`/`--output` to rebase URLs as relative to the output file. + 2. Use a root path via `-r`/`--root` to rebase URLs as absolute from the given root path. + 3. If you specify both then `-r`/`--root` takes precendence. +* When using clean-css as a library: + 1. Use a combination of `relativeTo` and `target` options for relative rebase (same as 1 in CLI). + 2. Use a combination of `relativeTo` and `root` options for absolute rebase (same as 2 in CLI). + 3. `root` takes precendence over `target` as in CLI. + +## Acknowledgments + +* Vincent Voyer ([@vvo](https://github.com/vvo)) for a patch with better + empty element regex and for inspiring us to do many performance improvements + in 0.4 release. +* Isaac ([@facelessuser](https://github.com/facelessuser)) for pointing out + a flaw in clean-css' stateless mode. +* Jan Michael Alonzo ([@jmalonzo](https://github.com/jmalonzo)) for a patch + removing node.js' old `sys` package. +* [@XhmikosR](https://github.com/XhmikosR) for suggesting new features + (option to remove special comments and strip out URLs quotation) and + pointing out numerous improvements (JSHint, media queries). +* Anthony Barre ([@abarre](https://github.com/abarre)) for improvements to + `@import` processing, namely introducing the `--skip-import` / + `processImport` options. +* Simon Altschuler ([@altschuler](https://github.com/altschuler)) for fixing + `@import` processing inside comments. + +## License + +Clean-css is released under the [MIT License](https://github.com/GoalSmashers/clean-css/blob/master/LICENSE). diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/bin/cleancss b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/bin/cleancss new file mode 100755 index 000000000..e73ebd565 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/bin/cleancss @@ -0,0 +1,138 @@ +#!/usr/bin/env node + +var util = require('util'); +var fs = require('fs'); +var path = require('path'); +var CleanCSS = require('../index'); + +var commands = require('commander'); + +var packageConfig = fs.readFileSync(path.join(path.dirname(fs.realpathSync(process.argv[1])), '../package.json')); +var buildVersion = JSON.parse(packageConfig).version; + +var isWindows = process.platform == 'win32'; + +// Specify commander options to parse command line params correctly +commands + .version(buildVersion, '-v, --version') + .usage('[options] ') + .option('-b, --keep-line-breaks', 'Keep line breaks') + .option('--s0', 'Remove all special comments, i.e. /*! comment */') + .option('--s1', 'Remove all special comments but the first one') + .option('-r, --root [root-path]', 'Set a root path to which resolve absolute @import rules') + .option('-o, --output [output-file]', 'Use [output-file] as output instead of STDOUT') + .option('-s, --skip-import', 'Disable @import processing') + .option('--skip-rebase', 'Disable URLs rebasing') + .option('--skip-advanced', 'Disable advanced optimizations - selector & property merging, reduction, etc.') + .option('--selectors-merge-mode [ie8|*]', 'Use `ie8` for compatibility mode, `*` for merge all (default).') + .option('-d, --debug', 'Shows debug information (minification time & compression efficiency)'); + +commands.on('--help', function() { + util.puts(' Examples:\n'); + util.puts(' %> cleancss one.css'); + util.puts(' %> cleancss -o one-min.css one.css'); + if (isWindows) { + util.puts(' %> type one.css two.css three.css | cleancss -o merged-and-minified.css'); + } else { + util.puts(' %> cat one.css two.css three.css | cleancss -o merged-and-minified.css'); + util.puts(' %> cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz'); + } + util.puts(''); + process.exit(); +}); + +commands.parse(process.argv); + +var options = { + source: null, + target: null +}; +var cleanOptions = {}; +var fromStdin = !process.env['__DIRECT__'] && !process.stdin.isTTY; + +// If no sensible data passed in just print help and exit +if (!fromStdin && commands.args.length == 0) { + commands.outputHelp(); + return 0; +} + +// Now coerce commands into CleanCSS configuration... +if (commands.output) + cleanOptions.target = options.target = commands.output; +if (commands.keepLineBreaks) + cleanOptions.keepBreaks = true; +if (commands.s1) + cleanOptions.keepSpecialComments = 1; +if (commands.s0) + cleanOptions.keepSpecialComments = 0; +if (commands.root) + cleanOptions.root = commands.root; +if (commands.skipImport) + cleanOptions.processImport = false; +if (commands.skipRebase) + cleanOptions.noRebase = true; +if (commands.skipAdvanced) + cleanOptions.noAdvanced = true; +if (commands.selectorsMergeMode) + cleanOptions.selectorsMergeMode = commands.selectorsMergeMode; +if (commands.debug) + cleanOptions.debug = true; +if (commands.args.length > 0) { + var source = commands.args[0]; + options.source = source; + cleanOptions.relativeTo = path.dirname(path.resolve(source)); +} + +// ... and do the magic! +if (options.source) { + fs.readFile(options.source, 'utf8', function(error, data) { + if (error) + throw error; + output(minify(data)); + }); +} else { + var stdin = process.openStdin(); + stdin.setEncoding('utf-8'); + var data = ''; + stdin.on('data', function(chunk) { + data += chunk; + }); + stdin.on('end', function() { + output(minify(data)); + }); +} + +function minify(data) { + var minifier = new CleanCSS(cleanOptions); + var minified = minifier.minify(data); + + if (cleanOptions.debug) { + console.error('Original: %d bytes', minifier.stats.originalSize); + console.error('Minified: %d bytes', minifier.stats.minifiedSize); + console.error('Efficiency: %d%', ~~(minifier.stats.efficiency * 10000) / 100.0); + console.error('Time spent: %dms', minifier.stats.timeSpent); + } + + outputFeedback(minifier.errors, true); + outputFeedback(minifier.warnings); + + if (minifier.errors.length > 0) + process.exit(1); + + return minified; +} + +function output(minified) { + if (options.target) + fs.writeFileSync(options.target, minified, 'utf8'); + else + process.stdout.write(minified); +}; + +function outputFeedback(messages, isError) { + var prefix = isError ? '\x1B[31mERROR\x1B[39m:' : 'WARNING:'; + + messages.forEach(function(message) { + console.error('%s %s', prefix, message); + }); +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/index.js new file mode 100644 index 000000000..d7b05030f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/clean'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/clean.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/clean.js new file mode 100644 index 000000000..d8768045c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/clean.js @@ -0,0 +1,323 @@ +/** + * Clean-css - https://github.com/GoalSmashers/clean-css + * Released under the terms of MIT license + * + * Copyright (C) 2011-2013 GoalSmashers.com + */ + +var ColorShortener = require('./colors/shortener'); +var ColorHSLToHex = require('./colors/hsl-to-hex'); +var ColorRGBToHex = require('./colors/rgb-to-hex'); +var ColorLongToShortHex = require('./colors/long-to-short-hex'); + +var ShorthandNotations = require('./properties/shorthand-notations'); +var ImportInliner = require('./imports/inliner'); +var UrlRebase = require('./images/url-rebase'); +var EmptyRemoval = require('./selectors/empty-removal'); + +var CommentsProcessor = require('./text/comments'); +var ExpressionsProcessor = require('./text/expressions'); +var FreeTextProcessor = require('./text/free'); +var UrlsProcessor = require('./text/urls'); + +var SelectorsOptimizer = require('./selectors/optimizer'); + +module.exports = function(options) { + var lineBreak = process.platform == 'win32' ? '\r\n' : '\n'; + var stats = {}; + var context = { + errors: [], + warnings: [] + }; + + options = options || {}; + options.keepBreaks = options.keepBreaks || false; + + //active by default + if (options.processImport === undefined) + options.processImport = true; + + var minify = function(data) { + var startedAt; + if (options.debug) { + startedAt = process.hrtime(); + stats.originalSize = data.length; + } + + var replace = function() { + if (typeof arguments[0] == 'function') + arguments[0](); + else + data = data.replace.apply(data, arguments); + }; + + // replace function + if (options.benchmark) { + var originalReplace = replace; + replace = function(pattern, replacement) { + var name = typeof pattern == 'function' ? + /function (\w+)\(/.exec(pattern.toString())[1] : + pattern; + + var start = process.hrtime(); + originalReplace(pattern, replacement); + + var itTook = process.hrtime(start); + console.log('%d ms: ' + name, 1000 * itTook[0] + itTook[1] / 1000000.0); + }; + } + + var commentsProcessor = new CommentsProcessor( + 'keepSpecialComments' in options ? options.keepSpecialComments : '*', + options.keepBreaks, + lineBreak + ); + var expressionsProcessor = new ExpressionsProcessor(); + var freeTextProcessor = new FreeTextProcessor(); + var urlsProcessor = new UrlsProcessor(); + var importInliner = new ImportInliner(context); + + if (options.processImport) { + // inline all imports + replace(function inlineImports() { + data = importInliner.process(data, { + root: options.root || process.cwd(), + relativeTo: options.relativeTo + }); + }); + } + + replace(function escapeComments() { + data = commentsProcessor.escape(data); + }); + + // replace all escaped line breaks + replace(/\\(\r\n|\n)/mg, ''); + + // strip parentheses in urls if possible (no spaces inside) + replace(/url\((['"])([^\)]+)['"]\)/g, function(match, quote, url) { + var unsafeDataURI = url.indexOf('data:') === 0 && url.match(/data:\w+\/[^;]+;base64,/) === null; + if (url.match(/[ \t]/g) !== null || unsafeDataURI) + return 'url(' + quote + url + quote + ')'; + else + return 'url(' + url + ')'; + }); + + // strip parentheses in animation & font names + replace(/(animation|animation\-name|font|font\-family):([^;}]+)/g, function(match, propertyName, fontDef) { + return propertyName + ':' + fontDef.replace(/['"]([\w\-]+)['"]/g, '$1'); + }); + + // strip parentheses in @keyframes + replace(/@(\-moz\-|\-o\-|\-webkit\-)?keyframes ([^{]+)/g, function(match, prefix, name) { + prefix = prefix || ''; + return '@' + prefix + 'keyframes ' + (name.indexOf(' ') > -1 ? name : name.replace(/['"]/g, '')); + }); + + // IE shorter filters, but only if single (IE 7 issue) + replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\([^\)]+\))([;}'"])/g, function(match, filter, args, suffix) { + return filter.toLowerCase() + args + suffix; + }); + + replace(function escapeExpressions() { + data = expressionsProcessor.escape(data); + }); + + // strip parentheses in attribute values + replace(/\[([^\]]+)\]/g, function(match, content) { + var eqIndex = content.indexOf('='); + var singleQuoteIndex = content.indexOf('\''); + var doubleQuoteIndex = content.indexOf('"'); + if (eqIndex < 0 && singleQuoteIndex < 0 && doubleQuoteIndex < 0) + return match; + if (singleQuoteIndex === 0 || doubleQuoteIndex === 0) + return match; + + var key = content.substring(0, eqIndex); + var value = content.substring(eqIndex + 1, content.length); + + if (/^['"](?:[a-zA-Z][a-zA-Z\d\-_]+)['"]$/.test(value)) + return '[' + key + '=' + value.substring(1, value.length - 1) + ']'; + else + return match; + }); + + replace(function escapeFreeText() { + data = freeTextProcessor.escape(data); + }); + + replace(function escapeUrls() { + data = urlsProcessor.escape(data); + }); + + // line breaks + replace(/[\r]?\n/g, ' '); + + // multiple whitespace + replace(/[\t ]+/g, ' '); + + // multiple semicolons (with optional whitespace) + replace(/;[ ]?;+/g, ';'); + + // multiple line breaks to one + replace(/ (?:\r\n|\n)/g, lineBreak); + replace(/(?:\r\n|\n)+/g, lineBreak); + + // remove spaces around selectors + replace(/ ([+~>]) /g, '$1'); + + // remove extra spaces inside content + replace(/([!\(\{\}:;=,\n]) /g, '$1'); + replace(/ ([!\)\{\};=,\n])/g, '$1'); + replace(/(?:\r\n|\n)\}/g, '}'); + replace(/([\{;,])(?:\r\n|\n)/g, '$1'); + replace(/ :([^\{\};]+)([;}])/g, ':$1$2'); + + // restore spaces inside IE filters (IE 7 issue) + replace(/progid:[^(]+\(([^\)]+)/g, function(match) { + return match.replace(/,/g, ', '); + }); + + // trailing semicolons + replace(/;\}/g, '}'); + + replace(function hsl2Hex() { + data = new ColorHSLToHex(data).process(); + }); + + replace(function rgb2Hex() { + data = new ColorRGBToHex(data).process(); + }); + + replace(function longToShortHex() { + data = new ColorLongToShortHex(data).process(); + }); + + replace(function shortenColors() { + data = new ColorShortener(data).process(); + }); + + // replace font weight with numerical value + replace(/(font\-weight|font):(normal|bold)([ ;\}!])(\w*)/g, function(match, property, weight, suffix, next) { + if (suffix == ' ' && next.length > 0 && !/[.\d]/.test(next)) + return match; + + if (weight == 'normal') + return property + ':400' + suffix + next; + else if (weight == 'bold') + return property + ':700' + suffix + next; + else + return match; + }); + + // zero + unit to zero + replace(/(\s|:|,)0(?:px|em|ex|cm|mm|in|pt|pc|%)/g, '$1' + '0'); + replace(/rect\(0(?:px|em|ex|cm|mm|in|pt|pc|%)/g, 'rect(0'); + + // fraction zeros removal + replace(/\.([1-9]*)0+(\D)/g, function(match, nonZeroPart, suffix) { + return (nonZeroPart ? '.' : '') + nonZeroPart + suffix; + }); + + // restore 0% in hsl/hsla + replace(/(hsl|hsla)\(([^\)]+)\)/g, function(match, colorFunction, colorDef) { + var tokens = colorDef.split(','); + if (tokens[1] == '0') + tokens[1] = '0%'; + if (tokens[2] == '0') + tokens[2] = '0%'; + return colorFunction + '(' + tokens.join(',') + ')'; + }); + + // none to 0 + replace(/(border|border-top|border-right|border-bottom|border-left|outline):none/g, '$1:0'); + + // background:none to background:0 0 + replace(/background:(?:none|transparent)([;}])/g, 'background:0 0$1'); + + // multiple zeros into one + replace(/box-shadow:0 0 0 0([^\.])/g, 'box-shadow:0 0$1'); + replace(/:0 0 0 0([^\.])/g, ':0$1'); + replace(/([: ,=\-])0\.(\d)/g, '$1.$2'); + + replace(function shorthandNotations() { + data = new ShorthandNotations(data).process(); + }); + + // restore rect(...) zeros syntax for 4 zeros + replace(/rect\(\s?0(\s|,)0[ ,]0[ ,]0\s?\)/g, 'rect(0$10$10$10)'); + + // remove universal selector when not needed (*#id, *.class etc) + replace(/\*([\.#:\[])/g, '$1'); + + // Restore spaces inside calc back + replace(/calc\([^\}]+\}/g, function(match) { + return match.replace(/\+/g, ' + '); + }); + + if (!options.noAdvanced) { + replace(function optimizeSelectors() { + data = new SelectorsOptimizer(data, context, { + keepBreaks: options.keepBreaks, + lineBreak: lineBreak, + selectorsMergeMode: options.selectorsMergeMode + }).process(); + }); + } + + replace(function restoreUrls() { + data = urlsProcessor.restore(data); + }); + replace(function rebaseUrls() { + data = options.noRebase ? data : new UrlRebase(options, context).process(data); + }); + replace(function restoreFreeText() { + data = freeTextProcessor.restore(data); + }); + replace(function restoreComments() { + data = commentsProcessor.restore(data); + }); + replace(function restoreExpressions() { + data = expressionsProcessor.restore(data); + }); + + // move first charset to the beginning + replace(function moveCharset() { + // get first charset in stylesheet + var match = data.match(/@charset [^;]+;/); + var firstCharset = match ? match[0] : null; + if (!firstCharset) + return; + + // reattach first charset and remove all subsequent + data = firstCharset + + (options.keepBreaks ? lineBreak : '') + + data.replace(new RegExp('@charset [^;]+;(' + lineBreak + ')?', 'g'), '').trim(); + }); + + replace(function removeEmptySelectors() { + data = new EmptyRemoval(data).process(); + }); + + // trim spaces at beginning and end + data = data.trim(); + + if (options.debug) { + var elapsed = process.hrtime(startedAt); + stats.timeSpent = ~~(elapsed[0] * 1e3 + elapsed[1] / 1e6); + stats.efficiency = 1 - data.length / stats.originalSize; + stats.minifiedSize = data.length; + } + + return data; + }; + + return { + errors: context.errors, + lineBreak: lineBreak, + options: options, + minify: minify, + stats: stats, + warnings: context.warnings + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/hsl-to-hex.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/hsl-to-hex.js new file mode 100644 index 000000000..09a676a4b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/hsl-to-hex.js @@ -0,0 +1,50 @@ +module.exports = function HSLToHex(data) { + // HSL to RGB converter. Both methods adapted from: + // http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + var hslToRgb = function(h, s, l) { + var r, g, b; + + h = ~~h / 360; + s = ~~s / 100; + l = ~~l / 100; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? + l * (1 + s) : + l + s - l * s; + var p = 2 * l - q; + r = hueToRgb(p, q, h + 1/3); + g = hueToRgb(p, q, h); + b = hueToRgb(p, q, h - 1/3); + } + + return [~~(r * 255), ~~(g * 255), ~~(b * 255)]; + }; + + var hueToRgb = function(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1/6) return p + (q - p) * 6 * t; + if (t < 1/2) return q; + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + }; + + return { + process: function() { + return data.replace(/hsl\((\d+),(\d+)%?,(\d+)%?\)/g, function(match, hue, saturation, lightness) { + var asRgb = hslToRgb(hue, saturation, lightness); + var redAsHex = asRgb[0].toString(16); + var greenAsHex = asRgb[1].toString(16); + var blueAsHex = asRgb[2].toString(16); + + return '#' + + ((redAsHex.length == 1 ? '0' : '') + redAsHex) + + ((greenAsHex.length == 1 ? '0' : '') + greenAsHex) + + ((blueAsHex.length == 1 ? '0' : '') + blueAsHex); + }); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/long-to-short-hex.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/long-to-short-hex.js new file mode 100644 index 000000000..87fa31b24 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/long-to-short-hex.js @@ -0,0 +1,12 @@ +module.exports = function LongToShortHex(data) { + return { + process: function() { + return data.replace(/([,: \(])#([0-9a-f]{6})/gi, function(match, prefix, color) { + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) + return prefix + '#' + color[0] + color[2] + color[4]; + else + return prefix + '#' + color; + }); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/rgb-to-hex.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/rgb-to-hex.js new file mode 100644 index 000000000..d235289be --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/rgb-to-hex.js @@ -0,0 +1,16 @@ +module.exports = function RGBToHex(data) { + return { + process: function() { + return data.replace(/rgb\((\d+),(\d+),(\d+)\)/g, function(match, red, green, blue) { + var redAsHex = parseInt(red, 10).toString(16); + var greenAsHex = parseInt(green, 10).toString(16); + var blueAsHex = parseInt(blue, 10).toString(16); + + return '#' + + ((redAsHex.length == 1 ? '0' : '') + redAsHex) + + ((greenAsHex.length == 1 ? '0' : '') + greenAsHex) + + ((blueAsHex.length == 1 ? '0' : '') + blueAsHex); + }); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/shortener.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/shortener.js new file mode 100644 index 000000000..7476f09ba --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/colors/shortener.js @@ -0,0 +1,174 @@ +module.exports = function Shortener(data) { + var COLORS = { + aliceblue: '#f0f8ff', + antiquewhite: '#faebd7', + aqua: '#0ff', + aquamarine: '#7fffd4', + azure: '#f0ffff', + beige: '#f5f5dc', + bisque: '#ffe4c4', + black: '#000', + blanchedalmond: '#ffebcd', + blue: '#00f', + blueviolet: '#8a2be2', + brown: '#a52a2a', + burlywood: '#deb887', + cadetblue: '#5f9ea0', + chartreuse: '#7fff00', + chocolate: '#d2691e', + coral: '#ff7f50', + cornflowerblue: '#6495ed', + cornsilk: '#fff8dc', + crimson: '#dc143c', + cyan: '#0ff', + darkblue: '#00008b', + darkcyan: '#008b8b', + darkgoldenrod: '#b8860b', + darkgray: '#a9a9a9', + darkgreen: '#006400', + darkkhaki: '#bdb76b', + darkmagenta: '#8b008b', + darkolivegreen: '#556b2f', + darkorange: '#ff8c00', + darkorchid: '#9932cc', + darkred: '#8b0000', + darksalmon: '#e9967a', + darkseagreen: '#8fbc8f', + darkslateblue: '#483d8b', + darkslategray: '#2f4f4f', + darkturquoise: '#00ced1', + darkviolet: '#9400d3', + deeppink: '#ff1493', + deepskyblue: '#00bfff', + dimgray: '#696969', + dodgerblue: '#1e90ff', + firebrick: '#b22222', + floralwhite: '#fffaf0', + forestgreen: '#228b22', + fuchsia: '#f0f', + gainsboro: '#dcdcdc', + ghostwhite: '#f8f8ff', + gold: '#ffd700', + goldenrod: '#daa520', + gray: '#808080', + green: '#008000', + greenyellow: '#adff2f', + honeydew: '#f0fff0', + hotpink: '#ff69b4', + indianred: '#cd5c5c', + indigo: '#4b0082', + ivory: '#fffff0', + khaki: '#f0e68c', + lavender: '#e6e6fa', + lavenderblush: '#fff0f5', + lawngreen: '#7cfc00', + lemonchiffon: '#fffacd', + lightblue: '#add8e6', + lightcoral: '#f08080', + lightcyan: '#e0ffff', + lightgoldenrodyellow: '#fafad2', + lightgray: '#d3d3d3', + lightgreen: '#90ee90', + lightpink: '#ffb6c1', + lightsalmon: '#ffa07a', + lightseagreen: '#20b2aa', + lightskyblue: '#87cefa', + lightslategray: '#778899', + lightsteelblue: '#b0c4de', + lightyellow: '#ffffe0', + lime: '#0f0', + limegreen: '#32cd32', + linen: '#faf0e6', + magenta: '#ff00ff', + maroon: '#800000', + mediumaquamarine: '#66cdaa', + mediumblue: '#0000cd', + mediumorchid: '#ba55d3', + mediumpurple: '#9370db', + mediumseagreen: '#3cb371', + mediumslateblue: '#7b68ee', + mediumspringgreen: '#00fa9a', + mediumturquoise: '#48d1cc', + mediumvioletred: '#c71585', + midnightblue: '#191970', + mintcream: '#f5fffa', + mistyrose: '#ffe4e1', + moccasin: '#ffe4b5', + navajowhite: '#ffdead', + navy: '#000080', + oldlace: '#fdf5e6', + olive: '#808000', + olivedrab: '#6b8e23', + orange: '#ffa500', + orangered: '#ff4500', + orchid: '#da70d6', + palegoldenrod: '#eee8aa', + palegreen: '#98fb98', + paleturquoise: '#afeeee', + palevioletred: '#db7093', + papayawhip: '#ffefd5', + peachpuff: '#ffdab9', + peru: '#cd853f', + pink: '#ffc0cb', + plum: '#dda0dd', + powderblue: '#b0e0e6', + purple: '#800080', + red: '#f00', + rosybrown: '#bc8f8f', + royalblue: '#4169e1', + saddlebrown: '#8b4513', + salmon: '#fa8072', + sandybrown: '#f4a460', + seagreen: '#2e8b57', + seashell: '#fff5ee', + sienna: '#a0522d', + silver: '#c0c0c0', + skyblue: '#87ceeb', + slateblue: '#6a5acd', + slategray: '#708090', + snow: '#fffafa', + springgreen: '#00ff7f', + steelblue: '#4682b4', + tan: '#d2b48c', + teal: '#008080', + thistle: '#d8bfd8', + tomato: '#ff6347', + turquoise: '#40e0d0', + violet: '#ee82ee', + wheat: '#f5deb3', + white: '#fff', + whitesmoke: '#f5f5f5', + yellow: '#ff0', + yellowgreen: '#9acd32' + }; + + var toHex = {}; + var toName = {}; + + for (var name in COLORS) { + var color = COLORS[name]; + if (name.length < color.length) + toName[color] = name; + else + toHex[name] = color; + } + + return { + toHex: toHex, + toName: toName, + + // replace color name with hex values if shorter (or the other way around) + process: function() { + [toHex, toName].forEach(function(conversion) { + var pattern = '(' + Object.keys(conversion).join('|') + ')'; + var colorSwitcher = function(match, prefix, colorValue, suffix) { + return prefix + conversion[colorValue.toLowerCase()] + suffix; + }; + data = data.replace(new RegExp('([ :,\\(])' + pattern + '([;\\}!\\) ])', 'ig'), colorSwitcher); + data = data.replace(new RegExp('(,)' + pattern + '(,)', 'ig'), colorSwitcher); + }); + + return data; + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rebase.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rebase.js new file mode 100644 index 000000000..5b249544e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rebase.js @@ -0,0 +1,34 @@ +var path = require('path'); + +var UrlRewriter = require('./url-rewriter'); + +module.exports = function UrlRebase(options, context) { + var process = function(data) { + var rebaseOpts = { + absolute: !!options.root, + relative: !options.root && !!options.target, + fromBase: options.relativeTo + }; + + if (!rebaseOpts.absolute && !rebaseOpts.relative) + return data; + + if (rebaseOpts.absolute && !!options.target) + context.warnings.push('Both \'root\' and output file given so rebasing URLs as absolute paths'); + + if (rebaseOpts.absolute) + rebaseOpts.toBase = path.resolve(options.root); + + if (rebaseOpts.relative) + rebaseOpts.toBase = path.resolve(path.dirname(options.target)); + + if (!rebaseOpts.fromBase || !rebaseOpts.toBase) + return data; + + return UrlRewriter.process(data, rebaseOpts); + }; + + return { + process: process + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rewriter.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rewriter.js new file mode 100644 index 000000000..b41056fdf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/images/url-rewriter.js @@ -0,0 +1,53 @@ +var path = require('path'); + +module.exports = { + process: function(data, options) { + var tempData = []; + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + + for (; nextEnd < data.length; ) { + nextStart = data.indexOf('url(', nextEnd); + if (nextStart == -1) + break; + + nextEnd = data.indexOf(')', nextStart + 4); + if (nextEnd == -1) + break; + + tempData.push(data.substring(cursor, nextStart)); + var url = data.substring(nextStart + 4, nextEnd).replace(/['"]/g, ''); + tempData.push('url(' + this._rebased(url, options) + ')'); + cursor = nextEnd + 1; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }, + + _rebased: function(url, options) { + var specialUrl = url[0] == '/' || + url.substring(url.length - 4) == '.css' || + url.indexOf('data:') === 0 || + /^https?:\/\//.exec(url) !== null || + /__\w+__/.exec(url) !== null; + var rebased; + + if (specialUrl) + return url; + + if (options.absolute) { + rebased = path + .resolve(path.join(options.fromBase, url)) + .replace(options.toBase, ''); + } else { + rebased = path.relative(options.toBase, path.join(options.fromBase, url)); + } + + return process.platform == 'win32' ? + rebased.replace(/\\/g, '/') : + rebased; + } +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/imports/inliner.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/imports/inliner.js new file mode 100644 index 000000000..f0c793ae4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/imports/inliner.js @@ -0,0 +1,144 @@ +var fs = require('fs'); +var path = require('path'); + +var UrlRewriter = require('../images/url-rewriter'); + +module.exports = function Inliner(context) { + var process = function(data, options) { + var tempData = []; + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + var isComment = commentScanner(data); + + options.relativeTo = options.relativeTo || options.root; + options._baseRelativeTo = options._baseRelativeTo || options.relativeTo; + options.visited = options.visited || []; + + for (; nextEnd < data.length; ) { + nextStart = data.indexOf('@import', cursor); + if (nextStart == -1) + break; + + if (isComment(nextStart)) { + cursor = nextStart + 1; + continue; + } + + nextEnd = data.indexOf(';', nextStart); + if (nextEnd == -1) + break; + + tempData.push(data.substring(cursor, nextStart)); + tempData.push(inlinedFile(data, nextStart, nextEnd, options)); + cursor = nextEnd + 1; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }; + + var commentScanner = function(data) { + var commentRegex = /(\/\*(?!\*\/)[\s\S]*?\*\/)/; + var lastEndIndex = 0; + var noComments = false; + + // test whether an index is located within a comment + var scanner = function(idx) { + var comment; + var localStartIndex = 0; + var localEndIndex = 0; + var globalStartIndex = 0; + var globalEndIndex = 0; + + // return if we know there are no more comments + if (noComments) + return false; + + comment = data.match(commentRegex); + + if (!comment) { + noComments = true; + return false; + } + + // get the indexes relative to the current data chunk + localStartIndex = comment.index; + localEndIndex = localStartIndex + comment[0].length; + + // calculate the indexes relative to the full original data + globalEndIndex = localEndIndex + lastEndIndex; + globalStartIndex = globalEndIndex - comment[0].length; + + // chop off data up to and including current comment block + data = data.substring(localEndIndex); + lastEndIndex = globalEndIndex; + + // re-run scan if comment ended before the idx + if (globalEndIndex < idx) + return scanner(idx); + + return globalEndIndex > idx && idx > globalStartIndex; + }; + + return scanner; + }; + + var inlinedFile = function(data, nextStart, nextEnd, options) { + var strippedImport = data + .substring(data.indexOf(' ', nextStart) + 1, nextEnd) + .replace(/^url\(/, '') + .replace(/['"]/g, ''); + + var separatorIndex = strippedImport.indexOf(' '); + var importedFile = strippedImport + .substring(0, separatorIndex > 0 ? separatorIndex : strippedImport.length) + .replace(')', ''); + var mediaQuery = strippedImport + .substring(importedFile.length + 1) + .trim(); + + if (/^(http|https):\/\//.test(importedFile) || /^\/\//.test(importedFile)) + return '@import url(' + importedFile + ')' + (mediaQuery.length > 0 ? ' ' + mediaQuery : '') + ';'; + + var relativeTo = importedFile[0] == '/' ? + options.root : + options.relativeTo; + + var fullPath = path.resolve(path.join(relativeTo, importedFile)); + + if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isFile()) { + context.errors.push('Broken @import declaration of "' + importedFile + '"'); + return ''; + } + + if (options.visited.indexOf(fullPath) != -1) + return ''; + + options.visited.push(fullPath); + + var importedData = fs.readFileSync(fullPath, 'utf8'); + var importRelativeTo = path.dirname(fullPath); + importedData = UrlRewriter.process(importedData, { + relative: true, + fromBase: importRelativeTo, + toBase: options._baseRelativeTo + }); + + var inlinedData = process(importedData, { + root: options.root, + relativeTo: importRelativeTo, + _baseRelativeTo: options.baseRelativeTo, + visited: options.visited + }); + return mediaQuery.length > 0 ? + '@media ' + mediaQuery + '{' + inlinedData + '}' : + inlinedData; + }; + + return { + // Inlines all imports taking care of repetitions, unknown files, and circular dependencies + process: process + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/optimizer.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/optimizer.js new file mode 100644 index 000000000..6106f379e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/optimizer.js @@ -0,0 +1,228 @@ +module.exports = function Optimizer() { + var overridable = { + 'animation-delay': ['animation'], + 'animation-direction': ['animation'], + 'animation-duration': ['animation'], + 'animation-fill-mode': ['animation'], + 'animation-iteration-count': ['animation'], + 'animation-name': ['animation'], + 'animation-play-state': ['animation'], + 'animation-timing-function': ['animation'], + '-moz-animation-delay': ['-moz-animation'], + '-moz-animation-direction': ['-moz-animation'], + '-moz-animation-duration': ['-moz-animation'], + '-moz-animation-fill-mode': ['-moz-animation'], + '-moz-animation-iteration-count': ['-moz-animation'], + '-moz-animation-name': ['-moz-animation'], + '-moz-animation-play-state': ['-moz-animation'], + '-moz-animation-timing-function': ['-moz-animation'], + '-o-animation-delay': ['-o-animation'], + '-o-animation-direction': ['-o-animation'], + '-o-animation-duration': ['-o-animation'], + '-o-animation-fill-mode': ['-o-animation'], + '-o-animation-iteration-count': ['-o-animation'], + '-o-animation-name': ['-o-animation'], + '-o-animation-play-state': ['-o-animation'], + '-o-animation-timing-function': ['-o-animation'], + '-webkit-animation-delay': ['-webkit-animation'], + '-webkit-animation-direction': ['-webkit-animation'], + '-webkit-animation-duration': ['-webkit-animation'], + '-webkit-animation-fill-mode': ['-webkit-animation'], + '-webkit-animation-iteration-count': ['-webkit-animation'], + '-webkit-animation-name': ['-webkit-animation'], + '-webkit-animation-play-state': ['-webkit-animation'], + '-webkit-animation-timing-function': ['-webkit-animation'], + 'background-attachment': ['background'], + 'background-clip': ['background'], + 'background-color': ['background'], + 'background-image': ['background'], + 'background-origin': ['background'], + 'background-position': ['background'], + 'background-repeat': ['background'], + 'background-size': ['background'], + 'border-color': ['border'], + 'border-style': ['border'], + 'border-width': ['border'], + 'border-bottom': ['border'], + 'border-bottom-color': ['border-bottom', 'border-color', 'border'], + 'border-bottom-style': ['border-bottom', 'border-style', 'border'], + 'border-bottom-width': ['border-bottom', 'border-width', 'border'], + 'border-left': ['border'], + 'border-left-color': ['border-left', 'border-color', 'border'], + 'border-left-style': ['border-left', 'border-style', 'border'], + 'border-left-width': ['border-left', 'border-width', 'border'], + 'border-right': ['border'], + 'border-right-color': ['border-right', 'border-color', 'border'], + 'border-right-style': ['border-right', 'border-style', 'border'], + 'border-right-width': ['border-right', 'border-width', 'border'], + 'border-top': ['border'], + 'border-top-color': ['border-top', 'border-color', 'border'], + 'border-top-style': ['border-top', 'border-style', 'border'], + 'border-top-width': ['border-top', 'border-width', 'border'], + 'font-family': ['font'], + 'font-size': ['font'], + 'font-style': ['font'], + 'font-variant': ['font'], + 'font-weight': ['font'], + 'list-style-image': ['list'], + 'list-style-position': ['list'], + 'list-style-type': ['list'], + 'margin-bottom': ['margin'], + 'margin-left': ['margin'], + 'margin-right': ['margin'], + 'margin-top': ['margin'], + 'outline-color': ['outline'], + 'outline-style': ['outline'], + 'outline-width': ['outline'], + 'padding-bottom': ['padding'], + 'padding-left': ['padding'], + 'padding-right': ['padding'], + 'padding-top': ['padding'], + 'transition-delay': ['transition'], + 'transition-duration': ['transition'], + 'transition-property': ['transition'], + 'transition-timing-function': ['transition'], + '-moz-transition-delay': ['-moz-transition'], + '-moz-transition-duration': ['-moz-transition'], + '-moz-transition-property': ['-moz-transition'], + '-moz-transition-timing-function': ['-moz-transition'], + '-o-transition-delay': ['-o-transition'], + '-o-transition-duration': ['-o-transition'], + '-o-transition-property': ['-o-transition'], + '-o-transition-timing-function': ['-o-transition'], + '-webkit-transition-delay': ['-webkit-transition'], + '-webkit-transition-duration': ['-webkit-transition'], + '-webkit-transition-property': ['-webkit-transition'], + '-webkit-transition-timing-function': ['-webkit-transition'] + }; + + var overrides = {}; + for (var granular in overridable) { + for (var i = 0; i < overridable[granular].length; i++) { + var coarse = overridable[granular][i]; + var list = overrides[coarse]; + + if (list) + list.push(granular); + else + overrides[coarse] = [granular]; + } + } + + var tokenize = function(body) { + var tokens = body.split(';'); + var keyValues = []; + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + if (token === '') + continue; + + var firstColon = token.indexOf(':'); + keyValues.push([ + token.substring(0, firstColon), + token.substring(firstColon + 1), + token.indexOf('!important') > -1 + ]); + } + + return keyValues; + }; + + var optimize = function(tokens, allowAdjacent) { + var merged = []; + var properties = []; + var lastProperty = null; + var rescanTrigger = {}; + + var removeOverridenBy = function(property, isImportant) { + var overrided = overrides[property]; + for (var i = 0, l = overrided.length; i < l; i++) { + for (var j = 0; j < properties.length; j++) { + if (properties[j] != overrided[i] || (merged[j][2] && !isImportant)) + continue; + + merged.splice(j, 1); + properties.splice(j, 1); + j -= 1; + } + } + }; + + var mergeablePosition = function(position) { + if (allowAdjacent === false || allowAdjacent === true) + return allowAdjacent; + + return allowAdjacent.indexOf(position) > -1; + }; + + tokensLoop: + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + var property = token[0]; + var isImportant = token[2]; + var _property = (property == '-ms-filter' || property == 'filter') ? + (lastProperty == 'background' || lastProperty == 'background-image' ? lastProperty : property) : + property; + var toOverridePosition = 0; + + // comment is necessary - we assume that if two properties are one after another + // then it is intentional way of redefining property which may not be widely supported + // e.g. a{display:inline-block;display:-moz-inline-box} + // however if `mergeablePosition` yields true then the rule does not apply + // (e.g merging two adjacent selectors: `a{display:block}a{display:block}`) + if (_property != lastProperty || mergeablePosition(i)) { + while (true) { + toOverridePosition = properties.indexOf(_property, toOverridePosition); + if (toOverridePosition == -1) + break; + + if (merged[toOverridePosition][2] && !isImportant) + continue tokensLoop; + + merged.splice(toOverridePosition, 1); + properties.splice(toOverridePosition, 1); + } + } + + merged.push(token); + properties.push(_property); + + // certain properties (see values of `overridable`) should trigger removal of + // more granular properties (see keys of `overridable`) + if (rescanTrigger[_property]) + removeOverridenBy(_property, isImportant); + + // add rescan triggers - if certain property appears later in the list a rescan needs + // to be triggered, e.g 'border-top' triggers a rescan after 'border-top-width' and + // 'border-top-color' as they can be removed + for (var j = 0, list = overridable[_property] || [], m = list.length; j < m; j++) + rescanTrigger[list[j]] = true; + + lastProperty = _property; + } + + return merged; + }; + + var rebuild = function(tokens) { + var flat = []; + + for (var i = 0, l = tokens.length; i < l; i++) { + flat.push(tokens[i][0] + ':' + tokens[i][1]); + } + + return flat.join(';'); + }; + + return { + process: function(body, allowAdjacent) { + var tokens = tokenize(body); + if (tokens.length < 2) + return body; + + var optimized = optimize(tokens, allowAdjacent); + return rebuild(optimized); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/shorthand-notations.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/shorthand-notations.js new file mode 100644 index 000000000..f29b2d36c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/properties/shorthand-notations.js @@ -0,0 +1,50 @@ +module.exports = function ShorthandNotations(data) { + // shorthand notations + var shorthandRegex = function(repeats, hasSuffix) { + var pattern = '(padding|margin|border\\-width|border\\-color|border\\-style|border\\-radius):'; + for (var i = 0; i < repeats; i++) + pattern += '([\\d\\w\\.%#\\(\\),]+)' + (i < repeats - 1 ? ' ' : ''); + return new RegExp(pattern + (hasSuffix ? '([;}])' : ''), 'g'); + }; + + var from4Values = function() { + return data.replace(shorthandRegex(4), function(match, property, size1, size2, size3, size4) { + if (size1 === size2 && size1 === size3 && size1 === size4) + return property + ':' + size1; + else if (size1 === size3 && size2 === size4) + return property + ':' + size1 + ' ' + size2; + else if (size2 === size4) + return property + ':' + size1 + ' ' + size2 + ' ' + size3; + else + return match; + }); + }; + + var from3Values = function() { + return data.replace(shorthandRegex(3, true), function(match, property, size1, size2, size3, suffix) { + if (size1 === size2 && size1 === size3) + return property + ':' + size1 + suffix; + else if (size1 === size3) + return property + ':' + size1 + ' ' + size2 + suffix; + else + return match; + }); + }; + + var from2Values = function() { + return data.replace(shorthandRegex(2, true), function(match, property, size1, size2, suffix) { + if (size1 === size2) + return property + ':' + size1 + suffix; + else + return match; + }); + }; + + return { + process: function() { + data = from4Values(); + data = from3Values(); + return from2Values(); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/empty-removal.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/empty-removal.js new file mode 100644 index 000000000..ee193c165 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/empty-removal.js @@ -0,0 +1,30 @@ +module.exports = function EmptyRemoval(data) { + var stripEmpty = function(cssData) { + var tempData = []; + var nextEmpty = 0; + var cursor = 0; + + for (; nextEmpty < cssData.length; ) { + nextEmpty = cssData.indexOf('{}', cursor); + if (nextEmpty == -1) + break; + + var startsAt = nextEmpty - 1; + while (cssData[startsAt] && cssData[startsAt] != '}' && cssData[startsAt] != '{') + startsAt--; + + tempData.push(cssData.substring(cursor, startsAt + 1)); + cursor = nextEmpty + 2; + } + + return tempData.length > 0 ? + stripEmpty(tempData.join('') + cssData.substring(cursor, cssData.length)) : + cssData; + }; + + return { + process: function() { + return stripEmpty(data); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/optimizer.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/optimizer.js new file mode 100644 index 000000000..da7299864 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/optimizer.js @@ -0,0 +1,221 @@ +var Tokenizer = require('./tokenizer'); +var PropertyOptimizer = require('../properties/optimizer'); + +module.exports = function Optimizer(data, context, options) { + var specialSelectors = { + '*': /\-(moz|ms|o|webkit)\-/, + 'ie8': /(\-moz\-|\-ms\-|\-o\-|\-webkit\-|:not|:target|:visited|:empty|:first\-of|:last|:nth|:only|:root)/ + }; + + var propertyOptimizer = new PropertyOptimizer(); + + var cleanUpSelector = function(selectors) { + var plain = []; + selectors = selectors.split(','); + + for (var i = 0, l = selectors.length; i < l; i++) { + var sel = selectors[i]; + + if (plain.indexOf(sel) == -1) + plain.push(sel); + } + + return plain.sort().join(','); + }; + + var isSpecial = function(selector) { + return specialSelectors[options.selectorsMergeMode || '*'].test(selector); + }; + + var removeDuplicates = function(tokens) { + var matched = {}; + var forRemoval = []; + + for (var i = 0, l = tokens.length; i < l; i++) { + if (typeof(tokens[i]) == 'string' || tokens[i].block) + continue; + + var selector = tokens[i].selector; + var body = tokens[i].body; + var id = body + '@' + selector; + var alreadyMatched = matched[id]; + + if (alreadyMatched) { + forRemoval.push(alreadyMatched[alreadyMatched.length - 1]); + alreadyMatched.push(i); + } else { + matched[id] = [i]; + } + } + + forRemoval = forRemoval.sort(function(a, b) { return a > b ? 1 : -1; }); + for (var j = 0, n = forRemoval.length; j < n; j++) { + tokens.splice(forRemoval[j] - j, 1); + } + }; + + var mergeAdjacent = function(tokens) { + var forRemoval = []; + var lastToken = { selector: null, body: null }; + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + + if (typeof(token) == 'string' || token.block) + continue; + + if (token.selector == lastToken.selector) { + var joinAt = [lastToken.body.split(';').length]; + lastToken.body = propertyOptimizer.process(lastToken.body + ';' + token.body, joinAt); + forRemoval.push(i); + } else if (token.body == lastToken.body && !isSpecial(token.selector) && !isSpecial(lastToken.selector)) { + lastToken.selector = cleanUpSelector(lastToken.selector + ',' + token.selector); + forRemoval.push(i); + } else { + lastToken = token; + } + } + + for (var j = 0, m = forRemoval.length; j < m; j++) { + tokens.splice(forRemoval[j] - j, 1); + } + }; + + var reduceNonAdjacent = function(tokens) { + var matched = {}; + var matchedMoreThanOnce = []; + var partiallyReduced = []; + var token, selector, selectors; + var removeEmpty = function(value) { + return value.length > 0 ? value : ''; + }; + + for (var i = 0, l = tokens.length; i < l; i++) { + token = tokens[i]; + selector = token.selector; + + if (typeof(token) == 'string' || token.block) + continue; + + selectors = selector.split(','); + if (selectors.length > 1) + selectors.unshift(selector); + + for (var j = 0, m = selectors.length; j < m; j++) { + var sel = selectors[j]; + var alreadyMatched = matched[sel]; + if (alreadyMatched) { + if (alreadyMatched.length == 1) + matchedMoreThanOnce.push(sel); + alreadyMatched.push(i); + } else { + matched[sel] = [i]; + } + } + } + + matchedMoreThanOnce.forEach(function(selector) { + var matchPositions = matched[selector]; + var bodies = []; + var joinsAt = []; + for (var j = 0, m = matchPositions.length; j < m; j++) { + var body = tokens[matchPositions[j]].body; + bodies.push(body); + joinsAt.push((joinsAt[j - 1] || 0) + body.split(';').length); + } + + var optimizedBody = propertyOptimizer.process(bodies.join(';'), joinsAt); + var optimizedTokens = optimizedBody.split(';'); + + var k = optimizedTokens.length - 1; + var currentMatch = matchPositions.length - 1; + + while (currentMatch >= 0) { + if (bodies[currentMatch].indexOf(optimizedTokens[k]) > -1 && k > -1) { + k -= 1; + continue; + } + + var tokenIndex = matchPositions[currentMatch]; + var token = tokens[tokenIndex]; + var reducedBody = optimizedTokens + .splice(k + 1) + .filter(removeEmpty) + .join(';'); + + if (token.selector == selector) { + token.body = reducedBody; + } else { + token._partials = token._partials || []; + token._partials.push(reducedBody); + + if (partiallyReduced.indexOf(tokenIndex) == -1) + partiallyReduced.push(tokenIndex); + } + + currentMatch -= 1; + } + }); + + // process those tokens which were partially reduced + // i.e. at least one of token's selectors saw reduction + // if all selectors were reduced to same value we can override it + for (i = 0, l = partiallyReduced.length; i < l; i++) { + token = tokens[partiallyReduced[i]]; + selectors = token.selector.split(','); + + if (token._partials.length == selectors.length && token.body != token._partials[0]) { + var newBody = token._partials[0]; + for (var k = 1, n = token._partials.length; k < n; k++) { + if (token._partials[k] != newBody) + break; + } + + if (k == n) + token.body = newBody; + } + + delete token._partials; + } + }; + + var optimize = function(tokens) { + tokens = (Array.isArray(tokens) ? tokens : [tokens]); + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + + if (token.selector) { + token.selector = cleanUpSelector(token.selector); + token.body = propertyOptimizer.process(token.body, false); + } else if (token.block) { + optimize(token.body); + } + } + + removeDuplicates(tokens); + mergeAdjacent(tokens); + reduceNonAdjacent(tokens); + }; + + var rebuild = function(tokens) { + return (Array.isArray(tokens) ? tokens : [tokens]) + .map(function(token) { + if (typeof token == 'string') + return token; + + if (token.block) + return token.block + '{' + rebuild(token.body) + '}'; + else + return token.selector + '{' + token.body + '}'; + }) + .join(options.keepBreaks ? options.lineBreak : ''); + }; + + return { + process: function() { + var tokenized = new Tokenizer(data, context).process(); + optimize(tokenized); + return rebuild(tokenized); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/tokenizer.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/tokenizer.js new file mode 100644 index 000000000..b368caced --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/selectors/tokenizer.js @@ -0,0 +1,127 @@ +module.exports = function Tokenizer(data, minifyContext) { + var whatsNext = function(context) { + var cursor = context.cursor; + var mode = context.mode; + var closest; + + if (mode == 'body') { + closest = data.indexOf('}', cursor); + return closest > -1 ? + [closest, 'bodyEnd'] : + null; + } + + var nextSpecial = data.indexOf('@', cursor); + var nextEscape = mode == 'top' ? data.indexOf('__ESCAPED_COMMENT_CLEAN_CSS', cursor) : -1; + var nextBodyStart = data.indexOf('{', cursor); + var nextBodyEnd = data.indexOf('}', cursor); + + closest = nextSpecial; + if (closest == -1 || (nextEscape > -1 && nextEscape < closest)) + closest = nextEscape; + if (closest == -1 || (nextBodyStart > -1 && nextBodyStart < closest)) + closest = nextBodyStart; + if (closest == -1 || (nextBodyEnd > -1 && nextBodyEnd < closest)) + closest = nextBodyEnd; + + if (closest == -1) + return; + if (nextEscape === closest) + return [closest, 'escape']; + if (nextBodyStart === closest) + return [closest, 'bodyStart']; + if (nextBodyEnd === closest) + return [closest, 'bodyEnd']; + if (nextSpecial === closest) + return [closest, 'special']; + }; + + var tokenize = function(context) { + var tokenized = []; + + context = context || { cursor: 0, mode: 'top' }; + + while (true) { + var next = whatsNext(context); + if (!next) { + var whatsLeft = data.substring(context.cursor); + if (whatsLeft.length > 0) { + tokenized.push(whatsLeft); + context.cursor += whatsLeft.length; + } + break; + } + + var nextSpecial = next[0]; + var what = next[1]; + var nextEnd; + var oldMode; + + if (what == 'special') { + var fragment = data.substring(nextSpecial, context.cursor + '@font-face'.length + 1); + var isSingle = fragment.indexOf('@import') === 0 || fragment.indexOf('@charset') === 0; + if (isSingle) { + nextEnd = data.indexOf(';', nextSpecial + 1); + tokenized.push(data.substring(context.cursor, nextEnd + 1)); + + context.cursor = nextEnd + 1; + } else { + nextEnd = data.indexOf('{', nextSpecial + 1); + var block = data.substring(context.cursor, nextEnd).trim(); + + var isFlat = fragment.indexOf('@font-face') === 0; + oldMode = context.mode; + context.cursor = nextEnd + 1; + context.mode = isFlat ? 'body' : 'block'; + var specialBody = tokenize(context); + context.mode = oldMode; + + tokenized.push({ block: block, body: specialBody }); + } + } else if (what == 'escape') { + nextEnd = data.indexOf('__', nextSpecial + 1); + var escaped = data.substring(context.cursor, nextEnd + 2); + tokenized.push(escaped); + + context.cursor = nextEnd + 2; + } else if (what == 'bodyStart') { + var selector = data.substring(context.cursor, nextSpecial).trim(); + + oldMode = context.mode; + context.cursor = nextSpecial + 1; + context.mode = 'body'; + var body = tokenize(context); + context.mode = oldMode; + + tokenized.push({ selector: selector, body: body }); + } else if (what == 'bodyEnd') { + // extra closing brace at the top level can be safely ignored + if (context.mode == 'top') { + var at = context.cursor; + var warning = data[context.cursor] == '}' ? + 'Unexpected \'}\' in \'' + data.substring(at - 20, at + 20) + '\'. Ignoring.' : + 'Unexpected content: \'' + data.substring(at, nextSpecial + 1) + '\'. Ignoring.'; + + minifyContext.warnings.push(warning); + context.cursor = nextSpecial + 1; + continue; + } + + if (context.mode != 'block') + tokenized = data.substring(context.cursor, nextSpecial); + + context.cursor = nextSpecial + 1; + + break; + } + } + + return tokenized; + }; + + return { + process: function() { + return tokenize(); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/comments.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/comments.js new file mode 100644 index 000000000..5667e7ec6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/comments.js @@ -0,0 +1,59 @@ +var EscapeStore = require('./escape-store'); + +module.exports = function Comments(keepSpecialComments, keepBreaks, lineBreak) { + var comments = new EscapeStore('COMMENT'); + + return { + // Strip special comments (/*! ... */) by replacing them by a special marker + // for further restoring. Plain comments are removed. It's done by scanning data using + // String#indexOf scanning instead of regexps to speed up the process. + escape: function(data) { + var tempData = []; + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + + for (; nextEnd < data.length; ) { + nextStart = data.indexOf('/*', nextEnd); + nextEnd = data.indexOf('*/', nextStart + 2); + if (nextStart == -1 || nextEnd == -1) + break; + + tempData.push(data.substring(cursor, nextStart)); + if (data[nextStart + 2] == '!') { + // in case of special comments, replace them with a placeholder + var comment = data.substring(nextStart, nextEnd + 2); + var placeholder = comments.store(comment); + tempData.push(placeholder); + } + cursor = nextEnd + 2; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }, + + restore: function(data) { + var restored = 0; + var breakSuffix = keepBreaks ? lineBreak : ''; + + return data.replace(new RegExp(comments.placeholderPattern + '(' + lineBreak + '| )?', 'g'), function(match, placeholder) { + restored++; + + switch (keepSpecialComments) { + case '*': + return comments.restore(placeholder) + breakSuffix; + case 1: + case '1': + return restored == 1 ? + comments.restore(placeholder) + breakSuffix : + ''; + case 0: + case '0': + return ''; + } + }); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/escape-store.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/escape-store.js new file mode 100644 index 000000000..8c2f07f90 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/escape-store.js @@ -0,0 +1,32 @@ +module.exports = function EscapeStore(placeholderRoot) { + placeholderRoot = 'ESCAPED_' + placeholderRoot + '_CLEAN_CSS'; + + var placeholderToData = {}; + var dataToPlaceholder = {}; + var count = 0; + var nextPlaceholder = function() { + return '__' + placeholderRoot + (count++) + '__'; + }; + var pattern = '(__' + placeholderRoot + '\\d{1,}__)'; + + return { + placeholderPattern: pattern, + + placeholderRegExp: new RegExp(pattern, 'g'), + + store: function(data) { + var placeholder = dataToPlaceholder[data]; + if (!placeholder) { + placeholder = nextPlaceholder(); + placeholderToData[placeholder] = data; + dataToPlaceholder[data] = placeholder; + } + + return placeholder; + }, + + restore: function(placeholder) { + return placeholderToData[placeholder]; + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/expressions.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/expressions.js new file mode 100644 index 000000000..2ca193bc5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/expressions.js @@ -0,0 +1,69 @@ +var EscapeStore = require('./escape-store'); + +module.exports = function Expressions() { + var expressions = new EscapeStore('EXPRESSION'); + + var findEnd = function(data, start) { + var end = start + 'expression'.length; + var level = 0; + var quoted = false; + + while(true) { + var next = data[end++]; + + if (quoted) { + quoted = next != '\'' && next != '"'; + } else { + quoted = next == '\'' || next == '"'; + + if (next == '(') + level++; + if (next == ')') + level--; + if (next == '}' && level == 1) { + end--; + level--; + } + } + + if (level === 0 || !next) + break; + } + + return end; + }; + + return { + // Escapes expressions by replacing them by a special + // marker for further restoring. It's done via string scanning + // instead of regexps to speed up the process. + escape: function(data) { + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + var tempData = []; + + for (; nextEnd < data.length; ) { + nextStart = data.indexOf('expression(', nextEnd); + if (nextStart == -1) + break; + + nextEnd = findEnd(data, nextStart); + + var expression = data.substring(nextStart, nextEnd); + var placeholder = expressions.store(expression); + tempData.push(data.substring(cursor, nextStart)); + tempData.push(placeholder); + cursor = nextEnd; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }, + + restore: function(data) { + return data.replace(expressions.placeholderRegExp, expressions.restore); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/free.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/free.js new file mode 100644 index 000000000..7ffee6331 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/free.js @@ -0,0 +1,76 @@ +var EscapeStore = require('./escape-store'); + +module.exports = function Free() { + var texts = new EscapeStore('FREE_TEXT'); + + var findNonEscapedEnd = function(data, matched, start) { + var end = start; + while (true) { + end = data.indexOf(matched, end); + + if (end > -1 && data[end - 1] == '\\') { + end += 1; + continue; + } else { + break; + } + } + + return end; + }; + + return { + // Strip content tags by replacing them by the a special + // marker for further restoring. It's done via string scanning + // instead of regexps to speed up the process. + escape: function(data) { + var tempData = []; + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + var matchedParenthesis = null; + var singleParenthesis = '\''; + var doubleParenthesis = '"'; + var dataLength = data.length; + + for (; nextEnd < data.length; ) { + var nextStartSingle = data.indexOf(singleParenthesis, nextEnd + 1); + var nextStartDouble = data.indexOf(doubleParenthesis, nextEnd + 1); + + if (nextStartSingle == -1) + nextStartSingle = dataLength; + if (nextStartDouble == -1) + nextStartDouble = dataLength; + + if (nextStartSingle < nextStartDouble) { + nextStart = nextStartSingle; + matchedParenthesis = singleParenthesis; + } else { + nextStart = nextStartDouble; + matchedParenthesis = doubleParenthesis; + } + + if (nextStart == -1) + break; + + nextEnd = findNonEscapedEnd(data, matchedParenthesis, nextStart + 1); + if (nextEnd == -1) + break; + + var text = data.substring(nextStart, nextEnd + 1); + var placeholder = texts.store(text); + tempData.push(data.substring(cursor, nextStart)); + tempData.push(placeholder); + cursor = nextEnd + 1; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }, + + restore: function(data) { + return data.replace(texts.placeholderRegExp, texts.restore); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/urls.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/urls.js new file mode 100644 index 000000000..007e41d2a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/lib/text/urls.js @@ -0,0 +1,39 @@ +var EscapeStore = require('./escape-store'); + +module.exports = function Urls() { + var urls = new EscapeStore('URL'); + + return { + // Strip urls by replacing them by a special + // marker for further restoring. It's done via string scanning + // instead of regexps to speed up the process. + escape: function(data) { + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + var tempData = []; + + for (; nextEnd < data.length; ) { + nextStart = data.indexOf('url(', nextEnd); + if (nextStart == -1) + break; + + nextEnd = data.indexOf(')', nextStart); + + var url = data.substring(nextStart, nextEnd + 1); + var placeholder = urls.store(url); + tempData.push(data.substring(cursor, nextStart)); + tempData.push(placeholder); + cursor = nextEnd + 1; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }, + + restore: function(data) { + return data.replace(urls.placeholderRegExp, urls.restore); + } + }; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/History.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/History.md new file mode 100644 index 000000000..2e665828c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/History.md @@ -0,0 +1,179 @@ + +2.0.0 / 2013-07-18 +================== + + * remove input methods (.prompt, .confirm, etc) + +1.3.2 / 2013-07-18 +================== + + * add support for sub-commands to co-exist with the original command + +1.3.1 / 2013-07-18 +================== + + * add quick .runningCommand hack so you can opt-out of other logic when running a sub command + +1.3.0 / 2013-07-09 +================== + + * add EACCES error handling + * fix sub-command --help + +1.2.0 / 2013-06-13 +================== + + * allow "-" hyphen as an option argument + * support for RegExp coercion + +1.1.1 / 2012-11-20 +================== + + * add more sub-command padding + * fix .usage() when args are present. Closes #106 + +1.1.0 / 2012-11-16 +================== + + * add git-style executable subcommand support. Closes #94 + +1.0.5 / 2012-10-09 +================== + + * fix `--name` clobbering. Closes #92 + * fix examples/help. Closes #89 + +1.0.4 / 2012-09-03 +================== + + * add `outputHelp()` method. + +1.0.3 / 2012-08-30 +================== + + * remove invalid .version() defaulting + +1.0.2 / 2012-08-24 +================== + + * add `--foo=bar` support [arv] + * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus] + +1.0.1 / 2012-08-03 +================== + + * fix issue #56 + * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode()) + +1.0.0 / 2012-07-05 +================== + + * add support for optional option descriptions + * add defaulting of `.version()` to package.json's version + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/Readme.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/Readme.md new file mode 100644 index 000000000..d1644012c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/Readme.md @@ -0,0 +1,195 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineapple'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineapple + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .outputHelp() + + Output help information without exiting. + +## .help() + + Output help information and exit immediately. + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/index.js new file mode 100644 index 000000000..d5778a75b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/index.js @@ -0,0 +1,847 @@ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var spawn = require('child_process').spawn; +var fs = require('fs'); +var exists = fs.existsSync; +var path = require('path'); +var dirname = path.dirname; +var basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description || ''; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this._execs = []; + this._args = []; + this._name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @param {String} [desc] + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name, desc){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + if (desc) cmd.description(desc); + if (desc) this.executables = true; + if (desc) this._execs[cmd._name] = true; + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + if (desc) return this; + return cmd; +}; + +/** + * Add an implicit `help [cmd]` subcommand + * which invokes `--help` for the given command. + * + * @api private + */ + +Command.prototype.addImplicitHelpCommand = function() { + this.command('help [cmd]', 'display help for [cmd]'); +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self._args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self._args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this._name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + // Leftover arguments need to be pushed back. Fixes issue #56 + if (parsed.args.length) args = parsed.args.concat(args); + + self._args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self._args.length) { + args[self._args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // implicit help + if (this.executables) this.addImplicitHelpCommand(); + + // store raw args + this.rawArgs = argv; + + // guess name + this._name = this._name || basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + var args = this.args = parsed.args; + + var result = this.parseArgs(this.args, parsed.unknown); + + // executable sub-commands + var name = result.args[0]; + if (this._execs[name]) return this.executeSubCommand(argv, args, parsed.unknown); + + return result; +}; + +/** + * Execute a sub-command executable. + * + * @param {Array} argv + * @param {Array} args + * @param {Array} unknown + * @api private + */ + +Command.prototype.executeSubCommand = function(argv, args, unknown) { + args = args.concat(unknown); + + if (!args.length) this.help(); + if ('help' == args[0] && 1 == args.length) this.help(); + + // --help + if ('help' == args[0]) { + args[0] = args[1]; + args[1] = '--help'; + } + + // executable + var dir = dirname(argv[1]); + var bin = basename(argv[1]) + '-' + args[0]; + + // check for ./ first + var local = path.join(dir, bin); + + // run it + args = args.slice(1); + var proc = spawn(local, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + proc.on('error', function(err){ + if (err.code == "ENOENT") { + console.error('\n %s(1) does not exist, try --help\n', bin); + } else if (err.code == "EACCES") { + console.error('\n %s(1) not executable. try chmod or run with root\n', bin); + } + }); + + this.runningCommand = proc; +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * This also normalizes equal sign and splits "--abc=def" into "--abc def". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg + , index; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) { + ret.push(arg.slice(0, index), arg.slice(index + 1)); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || ('-' == arg[0] && '-' != arg)) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this._args.length ? ' ' + args : ''); + + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return pad(cmd._name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args, 22) + + (cmd.description() + ? ' ' + cmd.description() + : ''); + }).join('\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this._name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Output help information for this command + * + * @api public + */ + +Command.prototype.outputHelp = function(){ + process.stdout.write(this.helpInformation()); + this.emit('--help'); +}; + +/** + * Output help information and exit. + * + * @api public + */ + +Command.prototype.help = function(){ + this.outputHelp(); + process.exit(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + cmd.outputHelp(); + process.exit(0); + } + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/package.json new file mode 100644 index 000000000..f7c8067f8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/node_modules/commander/package.json @@ -0,0 +1,41 @@ +{ + "name": "commander", + "version": "2.0.0", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.6.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineapple');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineapple\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .outputHelp()\n\n Output help information without exiting.\n\n## .help()\n\n Output help information and exit immediately.\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "_id": "commander@2.0.0", + "dist": { + "shasum": "d1e7e9cb1c2b0a1629e86ae995e3b34a356d25e8" + }, + "_from": "commander@2.0.x", + "_resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/package.json new file mode 100644 index 000000000..ea6dea61e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/clean-css/package.json @@ -0,0 +1,76 @@ +{ + "name": "clean-css", + "version": "2.0.2", + "author": { + "name": "Jakub Pawlowicz", + "email": "jakub@goalsmashers.com", + "url": "http://twitter.com/GoalSmashers" + }, + "description": "A well-tested CSS minifier", + "license": "MIT", + "keywords": [ + "css", + "minifier" + ], + "homepage": "https://github.com/GoalSmashers/clean-css", + "repository": { + "type": "git", + "url": "https://github.com/GoalSmashers/clean-css.git" + }, + "bugs": { + "url": "https://github.com/GoalSmashers/clean-css/issues" + }, + "bin": { + "cleancss": "./bin/cleancss" + }, + "main": "index.js", + "files": [ + "bin", + "lib", + "History.md", + "index.js", + "LICENSE" + ], + "scripts": { + "bench": "node ./test/bench.js", + "check": "jshint .", + "prepublish": "jshint .", + "test": "vows" + }, + "dependencies": { + "commander": "2.0.x" + }, + "devDependencies": { + "jshint": "2.3.x", + "vows": "0.7.x" + }, + "jshintConfig": { + "browser": false, + "camelcase": true, + "curly": false, + "eqeqeq": false, + "eqnull": true, + "immed": true, + "latedef": true, + "multistr": true, + "noarg": true, + "node": true, + "plusplus": false, + "quotmark": "single", + "strict": false, + "trailing": true, + "undef": true, + "unused": true + }, + "engines": { + "node": ">=0.8.0" + }, + "readme": "[![NPM version](https://badge.fury.io/js/clean-css.png)](https://badge.fury.io/js/clean-css)\n[![Build Status](https://secure.travis-ci.org/GoalSmashers/clean-css.png)](https://travis-ci.org/GoalSmashers/clean-css)\n[![Dependency Status](https://david-dm.org/GoalSmashers/clean-css.png)](https://david-dm.org/GoalSmashers/clean-css)\n[![devDependency Status](https://david-dm.org/GoalSmashers/clean-css/dev-status.png)](https://david-dm.org/GoalSmashers/clean-css#info=devDependencies)\n\n## What is clean-css?\n\nClean-css is a fast and efficient [node.js](http://nodejs.org/) library for minifying CSS files.\n\nAccording to [tests](https://github.com/GoalSmashers/css-minification-benchmark) it is one of the best available.\n\n\n## Usage\n\n### What are the requirements?\n\n```\nnode.js 0.8.0+ (tested on CentOS, Ubuntu, OS X 10.6+, and Windows 7+)\n```\n\n### How to install clean-css?\n\n```\nnpm install clean-css\n```\n\n### How to upgrade clean-css from 1.x to 2.x?\n\n#### Command-line interface (CLI)\n\n```\nnpm update clean-css\n```\n\nor point `package.json` to version 2.x. That's it!\n\n#### Node.js module\n\nUpdate `clean-css` as for CLI above.\nThen change your JavaScript code from:\n\n```js\nvar minimized = CleanCSS.process(source, options);\n```\n\ninto\n\n```js\nvar minimized = new CleanCSS(options).minify(source);\n```\n\nAnd you are done.\n\n### How to use clean-css CLI?\n\nClean-css accepts the following command line arguments (please make sure\nyou use `` as the very last argument to avoid potential issues):\n\n```\ncleancss [options] \n\n-h, --help Output usage information\n-v, --version Output the version number\n-b, --keep-line-breaks Keep line breaks\n--s0 Remove all special comments, i.e. /*! comment */\n--s1 Remove all special comments but the first one\n-r, --root [root-path] A root path to which resolve absolute @import rules\n and rebase relative URLs\n-o, --output [output-file] Use [output-file] as output instead of STDOUT\n-s, --skip-import Disable @import processing\n--skip-rebase Disable URLs rebasing\n--skip-advanced Disable advanced optimizations - selector & property merging,\n reduction, etc.\n--selectors-merge-mode [ie8|*] Use `ie8` for compatibility mode, `*` for merge all (default)\n-d, --debug Shows debug information (minification time & compression efficiency)\n```\n\n#### Examples:\n\nTo minify a **public.css** file into **public-min.css** do:\n\n```\ncleancss -o public-min.css public.css\n```\n\nTo minify the same **public.css** into the standard output skip the `-o` parameter:\n\n```\ncleancss public.css\n```\n\nMore likely you would like to concatenate a couple of files.\nIf you are on a Unix-like system:\n\n```bash\ncat one.css two.css three.css | cleancss -o merged-and-minified.css\n```\n\nOn Windows:\n\n```bat\ntype one.css two.css three.css | cleancss -o merged-and-minified.css\n```\n\nOr even gzip the result at once:\n\n```bash\ncat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz\n```\n\n### How to use clean-css programmatically?\n\n```js\nvar CleanCSS = require('clean-css');\nvar source = 'a{font-weight:bold;}';\nvar minimized = new CleanCSS().minify(source);\n```\n\nCleanCSS constructor accepts a hash as a parameter, i.e.,\n`new CleanCSS(options).minify(source)` with the following options available:\n\n* `keepSpecialComments` - `*` for keeping all (default), `1` for keeping first one only, `0` for removing all\n* `keepBreaks` - whether to keep line breaks (default is false)\n* `benchmark` - turns on benchmarking mode measuring time spent on cleaning up\n (run `npm run bench` to see example)\n* `root` - path to resolve absolute `@import` rules and rebase relative URLs\n* `relativeTo` - path with which to resolve relative `@import` rules and URLs\n* `processImport` - whether to process `@import` rules\n* `noRebase` - whether to skip URLs rebasing\n* `noAdvanced` - set to true to disable advanced optimizations - selector & property merging, reduction, etc.\n* `selectorsMergeMode` - `ie8` for IE8 compatibility mode, `*` for merging all (default)\n* `debug` - set to true to get minification statistics under `stats` property (see `test/custom-test.js` for examples)\n\n### What are the clean-css' dev commands?\n\nFirst clone the source, then run:\n\n* `npm run bench` for clean-css benchmarks (see [test/bench.js](https://github.com/GoalSmashers/clean-css/blob/master/test/bench.js) for details)\n* `npm run check` to check JS sources with [JSHint](https://github.com/jshint/jshint/)\n* `npm test` for the test suite\n\n## Tips & Tricks\n\n### How to preserve a comment block?\n\nUse the `/*!` notation instead of the standard one `/*`:\n\n```css\n/*!\n Important comments included in minified output.\n*/\n```\n\n### How to rebase relative image URLs\n\nClean-css will handle it automatically for you (since version 1.1) in the following cases:\n\n* When using the CLI:\n 1. Use an output path via `-o`/`--output` to rebase URLs as relative to the output file.\n 2. Use a root path via `-r`/`--root` to rebase URLs as absolute from the given root path.\n 3. If you specify both then `-r`/`--root` takes precendence.\n* When using clean-css as a library:\n 1. Use a combination of `relativeTo` and `target` options for relative rebase (same as 1 in CLI).\n 2. Use a combination of `relativeTo` and `root` options for absolute rebase (same as 2 in CLI).\n 3. `root` takes precendence over `target` as in CLI.\n\n## Acknowledgments\n\n* Vincent Voyer ([@vvo](https://github.com/vvo)) for a patch with better\n empty element regex and for inspiring us to do many performance improvements\n in 0.4 release.\n* Isaac ([@facelessuser](https://github.com/facelessuser)) for pointing out\n a flaw in clean-css' stateless mode.\n* Jan Michael Alonzo ([@jmalonzo](https://github.com/jmalonzo)) for a patch\n removing node.js' old `sys` package.\n* [@XhmikosR](https://github.com/XhmikosR) for suggesting new features\n (option to remove special comments and strip out URLs quotation) and\n pointing out numerous improvements (JSHint, media queries).\n* Anthony Barre ([@abarre](https://github.com/abarre)) for improvements to\n `@import` processing, namely introducing the `--skip-import` /\n `processImport` options.\n* Simon Altschuler ([@altschuler](https://github.com/altschuler)) for fixing\n `@import` processing inside comments.\n\n## License\n\nClean-css is released under the [MIT License](https://github.com/GoalSmashers/clean-css/blob/master/LICENSE).\n", + "readmeFilename": "README.md", + "_id": "clean-css@2.0.2", + "dist": { + "shasum": "4ac642a986523d58ca10b98e14404144b0ca7320" + }, + "_from": "clean-css@2.0.x", + "_resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.0.2.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/LICENSE new file mode 100644 index 000000000..451fc4550 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/README.md new file mode 100644 index 000000000..6ca19bd1e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/README.md @@ -0,0 +1,66 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.default_type +Sets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.) + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/mime.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/mime.js new file mode 100644 index 000000000..48be0c5e4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/mime.js @@ -0,0 +1,114 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + if (process.env.DEBUG_MIME && this.types[exts]) { + console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' + + this.types[exts] + ' to ' + type); + } + + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + + this._loading = file; + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); + + this._loading = null; +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase(); + return this.extensions[type]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +}; + +module.exports = mime; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/package.json new file mode 100644 index 000000000..39b19f9a9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "https://github.com/broofa/node-mime", + "type": "git" + }, + "version": "1.2.11", + "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/broofa/node-mime/issues" + }, + "_id": "mime@1.2.11", + "dist": { + "shasum": "ef63a602350a6db4e46b4b3b3d11338376a1a736" + }, + "_from": "mime@1.2.x", + "_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/test.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/test.js new file mode 100644 index 000000000..2cda1c7ad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/test.js @@ -0,0 +1,84 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); +var path = require('path'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); // normal file +eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase +eq('text/plain', mime.lookup('dir/text.txt')); // dir + file +eq('text/plain', mime.lookup('.text.txt')); // hidden file +eq('text/plain', mime.lookup('.txt')); // nameless +eq('text/plain', mime.lookup('txt')); // extension-only +eq('text/plain', mime.lookup('/txt')); // extension-less () +eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less +eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized +eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq('bin', mime.extension('application/octet-stream ')); +eq('html', mime.extension(' text/html; charset=UTF-8')); +eq('html', mime.extension('text/html; charset=UTF-8 ')); +eq('html', mime.extension('text/html; charset=UTF-8')); +eq('html', mime.extension('text/html ; charset=UTF-8')); +eq('html', mime.extension('text/html;charset=UTF-8')); +eq('html', mime.extension('text/Html;charset=UTF-8')); +eq(undefined, mime.extension('unrecognized')); + +// +// Test node.types lookups +// + +eq('application/font-woff', mime.lookup('file.woff')); +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); +eq('font/opentype', mime.lookup('file.otf')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +// +// Test for overlaps between mime.types and node.types +// + +var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime(); +apacheTypes.load(path.join(__dirname, 'types/mime.types')); +nodeTypes.load(path.join(__dirname, 'types/node.types')); + +var keys = [].concat(Object.keys(apacheTypes.types)) + .concat(Object.keys(nodeTypes.types)); +keys.sort(); +for (var i = 1; i < keys.length; i++) { + if (keys[i] == keys[i-1]) { + console.warn('Warning: ' + + 'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] + + ', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]); + } +} + +console.log('\nOK'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/mime.types b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/mime.types new file mode 100644 index 000000000..da8cd6918 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/node.types b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/node.types new file mode 100644 index 000000000..55b2cf794 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mime/types/node.types @@ -0,0 +1,77 @@ +# What: WebVTT +# Why: To allow formats intended for marking up external text track resources. +# http://dev.w3.org/html5/webvtt/ +# Added by: niftylettuce +text/vtt vtt + +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifes ('.manifest' extension) +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp + +# What: Lua file types +# Why: Googling around shows de-facto consensus on these +# Added by: creationix (Issue #45) +text/x-lua lua +application/x-lua-bytecode luac + +# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax +# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown +# Added by: avoidwork +text/x-markdown markdown md mkd + +# What: ini files +# Why: because they're just text files +# Added by: Matthew Kastor +text/plain ini + +# What: DASH Adaptive Streaming manifest +# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video +# Added by: eelcocramer +application/dash+xml mdp + +# What: OpenType font files - http://www.microsoft.com/typography/otspec/ +# Why: Browsers usually ignore the font MIME types and sniff the content, +# but Chrome, shows a warning if OpenType fonts aren't served with +# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png. +# Added by: alrra +font/opentype otf diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.npmignore new file mode 100644 index 000000000..9303c347e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.travis.yml b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.travis.yml new file mode 100644 index 000000000..84fd7ca24 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/LICENSE new file mode 100644 index 000000000..432d1aeb0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/examples/pow.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/examples/pow.js new file mode 100644 index 000000000..e6924212e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/index.js new file mode 100644 index 000000000..fda6de8a2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/package.json new file mode 100644 index 000000000..87527adcd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/package.json @@ -0,0 +1,37 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.5", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.4.0" + }, + "license": "MIT", + "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n", + "readmeFilename": "readme.markdown", + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "_id": "mkdirp@0.3.5", + "dist": { + "shasum": "cb96d427a7c19bf0ecba28825840b561227512c3" + }, + "_from": "mkdirp@~0.3.5", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/readme.markdown b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/readme.markdown new file mode 100644 index 000000000..83b0216ab --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/chmod.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/chmod.js new file mode 100644 index 000000000..520dcb8e9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/clobber.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/clobber.js new file mode 100644 index 000000000..0eb709987 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/mkdirp.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 000000000..b07cd70c1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm.js new file mode 100644 index 000000000..23a7abbd2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm_sync.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 000000000..f685f6090 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/race.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/race.js new file mode 100644 index 000000000..96a044763 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/rel.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/rel.js new file mode 100644 index 000000000..79858243a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return.js new file mode 100644 index 000000000..bce68e561 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return_sync.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 000000000..7c222d355 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/root.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/root.js new file mode 100644 index 000000000..97ad7a2f3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/sync.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/sync.js new file mode 100644 index 000000000..7530cada8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask.js new file mode 100644 index 000000000..64ccafe22 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask_sync.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 000000000..35bd5cbbf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/.npmignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/LICENSE new file mode 100644 index 000000000..a4a9aee0c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/README.md new file mode 100644 index 000000000..712bbe193 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/README.md @@ -0,0 +1,332 @@ +# Request -- Simplified HTTP client + +[![NPM](https://nodei.co/npm/request.png)](https://nodei.co/npm/request/) + +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers. + +```javascript +fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## Forms + +`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API. + +Url encoded forms are simple + +```javascript +request.post('http://service.com/upload', {form:{key:'value'}}) +// or +request.post('http://service.com/upload').form({key:'value'}) +``` + +For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you. + +```javascript +var r = request.post('http://service.com/upload') +var form = r.form() +form.append('my_field', 'my_value') +form.append('my_buffer', new Buffer([1, 2, 3])) +form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')) +form.append('remote_file', request('http://google.com/doodle.png')) +``` + +## HTTP Authentication + +```javascript +request.get('http://some.server.com/').auth('username', 'password', false); +// or +request.get('http://some.server.com/', { + 'auth': { + 'user': 'username', + 'pass': 'password', + 'sendImmediately': false + } +}); +``` + +If passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`. + +`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method). + +Digest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail). + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Ideally, you would take the body in the response + // and construct a URL that a user clicks on (like a sign in button). + // The verifier is only available in the response after a user has + // verified with twitter that they are authorizing your app. + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: access_token.oauth_verifier + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `qs` - object containing querystring values to be appended to the uri +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string. +* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request. +* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer. +* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example). +* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option. +* `jar` - Set to `true` if you want cookies to be remembered for future use, or define your custom cookie jar (see examples section) +* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services) +* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options. +* `localAddress` - Local interface to bind for network connections. + + +The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second is an http.ClientResponse object. The third is the response body String or Buffer. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.patch + +Same as request() but defaults to `method: "PATCH"`. + +```javascript +request.patch(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.iriscouch.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies are disabled by default (else, they would be used in subsequent requests). To enable cookies set jar to true (either in defaults or in the options sent). + +```javascript +var request = request.defaults({jar: true}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/index.js new file mode 100755 index 000000000..06b407df0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/index.js @@ -0,0 +1,149 @@ +// Copyright 2010-2012 Mikeal Rogers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var Cookie = require('cookie-jar') + , CookieJar = Cookie.Jar + , cookieJar = new CookieJar + + , copy = require('./lib/copy') + , Request = require('./request') + ; + + + +// organize params for patch, post, put, head, del +function initParams(uri, options, callback) { + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + uri = options.uri + } + return { uri: uri, options: options, callback: callback } +} + +function request (uri, options, callback) { + if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.') + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + } + + options = copy(options) + + if (callback) options.callback = callback + var r = new Request(options) + return r +} + +module.exports = request + +request.Request = Request; + +request.debug = process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG) + +request.initParams = initParams + +request.defaults = function (options, requester) { + var def = function (method) { + var d = function (uri, opts, callback) { + var params = initParams(uri, opts, callback) + for (var i in options) { + if (params.options[i] === undefined) params.options[i] = options[i] + } + if(typeof requester === 'function') { + if(method === request) { + method = requester + } else { + params.options._requester = requester + } + } + return method(params.options, params.callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.patch = def(request.patch) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = request.jar + return de +} + +request.forever = function (agentOptions, optionsArg) { + var options = {} + if (optionsArg) { + for (option in optionsArg) { + options[option] = optionsArg[option] + } + } + if (agentOptions) options.agentOptions = agentOptions + options.forever = true + return request.defaults(options) +} + +request.get = request +request.post = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'POST' + return request(params.uri || null, params.options, params.callback) +} +request.put = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'PUT' + return request(params.uri || null, params.options, params.callback) +} +request.patch = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'PATCH' + return request(params.uri || null, params.options, params.callback) +} +request.head = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'HEAD' + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(params.uri || null, params.options, params.callback) +} +request.del = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'DELETE' + if(typeof params.options._requester === 'function') { + request = params.options._requester + } + return request(params.uri || null, params.options, params.callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (str && str.uri) str = str.uri + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/copy.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/copy.js new file mode 100644 index 000000000..56831ff80 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/copy.js @@ -0,0 +1,8 @@ +module.exports = +function copy (obj) { + var o = {} + Object.keys(obj).forEach(function (i) { + o[i] = obj[i] + }) + return o +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/debug.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/debug.js new file mode 100644 index 000000000..462259f4d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/debug.js @@ -0,0 +1,5 @@ +module.exports = +function debug () { + if (/\brequest\b/.test(process.env.NODE_DEBUG)) + console.error('REQUEST %s', util.format.apply(util, arguments)) +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/getSafe.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/getSafe.js new file mode 100644 index 000000000..28e07ea56 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/lib/getSafe.js @@ -0,0 +1,34 @@ +// Safe toJSON +module.exports = +function getSafe (self, uuid) { + if (typeof self === 'object' || typeof self === 'function') var safe = {} + if (Array.isArray(self)) var safe = [] + + var recurse = [] + + Object.defineProperty(self, uuid, {}) + + var attrs = Object.keys(self).filter(function (i) { + if (i === uuid) return false + if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true + return !(Object.getOwnPropertyDescriptor(self[i], uuid)) + }) + + + for (var i=0;i + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , parse = require('url').parse + ; + +/** + * Valid keys. + */ + +var keys = + [ 'acl' + , 'location' + , 'logging' + , 'notification' + , 'partNumber' + , 'policy' + , 'requestPayment' + , 'torrent' + , 'uploadId' + , 'uploads' + , 'versionId' + , 'versioning' + , 'versions' + , 'website' + ] + +/** + * Return an "Authorization" header value with the given `options` + * in the form of "AWS :" + * + * @param {Object} options + * @return {String} + * @api private + */ + +function authorization (options) { + return 'AWS ' + options.key + ':' + sign(options) +} + +module.exports = authorization +module.exports.authorization = authorization + +/** + * Simple HMAC-SHA1 Wrapper + * + * @param {Object} options + * @return {String} + * @api private + */ + +function hmacSha1 (options) { + return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') +} + +module.exports.hmacSha1 = hmacSha1 + +/** + * Create a base64 sha1 HMAC for `options`. + * + * @param {Object} options + * @return {String} + * @api private + */ + +function sign (options) { + options.message = stringToSign(options) + return hmacSha1(options) +} +module.exports.sign = sign + +/** + * Create a base64 sha1 HMAC for `options`. + * + * Specifically to be used with S3 presigned URLs + * + * @param {Object} options + * @return {String} + * @api private + */ + +function signQuery (options) { + options.message = queryStringToSign(options) + return hmacSha1(options) +} +module.exports.signQuery= signQuery + +/** + * Return a string for sign() with the given `options`. + * + * Spec: + * + * \n + * \n + * \n + * \n + * [headers\n] + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +function stringToSign (options) { + var headers = options.amazonHeaders || '' + if (headers) headers += '\n' + var r = + [ options.verb + , options.md5 + , options.contentType + , options.date.toUTCString() + , headers + options.resource + ] + return r.join('\n') +} +module.exports.queryStringToSign = stringToSign + +/** + * Return a string for sign() with the given `options`, but is meant exclusively + * for S3 presigned URLs + * + * Spec: + * + * \n + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +function queryStringToSign (options){ + return 'GET\n\n\n' + options.date + '\n' + options.resource +} +module.exports.queryStringToSign = queryStringToSign + +/** + * Perform the following: + * + * - ignore non-amazon headers + * - lowercase fields + * - sort lexicographically + * - trim whitespace between ":" + * - join with newline + * + * @param {Object} headers + * @return {String} + * @api private + */ + +function canonicalizeHeaders (headers) { + var buf = [] + , fields = Object.keys(headers) + ; + for (var i = 0, len = fields.length; i < len; ++i) { + var field = fields[i] + , val = headers[field] + , field = field.toLowerCase() + ; + if (0 !== field.indexOf('x-amz')) continue + buf.push(field + ':' + val) + } + return buf.sort().join('\n') +} +module.exports.canonicalizeHeaders = canonicalizeHeaders + +/** + * Perform the following: + * + * - ignore non sub-resources + * - sort lexicographically + * + * @param {String} resource + * @return {String} + * @api private + */ + +function canonicalizeResource (resource) { + var url = parse(resource, true) + , path = url.pathname + , buf = [] + ; + + Object.keys(url.query).forEach(function(key){ + if (!~keys.indexOf(key)) return + var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) + buf.push(key + val) + }) + + return path + (buf.length ? '?' + buf.sort().join('&') : '') +} +module.exports.canonicalizeResource = canonicalizeResource diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/aws-sign/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/aws-sign/package.json new file mode 100644 index 000000000..536d7860d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/aws-sign/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "aws-sign", + "description": "AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/aws-sign" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "aws-sign\n========\n\nAWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mikeal/aws-sign/issues" + }, + "_id": "aws-sign@0.3.0", + "dist": { + "shasum": "c142174811f7a92322fd560632de1f91ac02322d" + }, + "_from": "aws-sign@~0.3.0", + "_resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/LICENSE new file mode 100644 index 000000000..a4a9aee0c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/README.md new file mode 100644 index 000000000..bcd8f8d44 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/README.md @@ -0,0 +1,4 @@ +cookie-jar +========== + +Cookie Jar. Originally pulled from LearnBoost/tobi, maintained as vendor in request, now a standalone module. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/index.js new file mode 100644 index 000000000..7d54d940c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/index.js @@ -0,0 +1,67 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + var p = pair.indexOf('='); + var key = p > 0 ? pair.substring(0, p).trim() : pair.trim(); + var lowerCasedKey = key.toLowerCase(); + var value = p > 0 ? pair.substring(p + 1).trim() : true; + + if (!obj.name) { + // First key is the name + obj.name = key; + obj.value = value; + } + else if (lowerCasedKey === 'httponly') { + obj.httpOnly = value; + } + else { + obj[lowerCasedKey] = value; + } + return obj; + }, this); + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim(): req + ? url.parse(req.url).pathname: '/'; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; + +module.exports.Jar = require('./jar') \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/jar.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/jar.js new file mode 100644 index 000000000..34920e062 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/package.json new file mode 100644 index 000000000..fec0c7f30 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/package.json @@ -0,0 +1,34 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "cookie-jar", + "description": "Cookie Jar. Originally pulled form tobi, maintained as vendor in request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/cookie-jar" + }, + "main": "index.js", + "scripts": { + "test": "node tests/run.js" + }, + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "cookie-jar\n==========\n\nCookie Jar. Originally pulled from LearnBoost/tobi, maintained as vendor in request, now a standalone module.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mikeal/cookie-jar/issues" + }, + "_id": "cookie-jar@0.3.0", + "dist": { + "shasum": "ddb1489baf56b1c96c99630cf54e6db5be914392" + }, + "_from": "cookie-jar@~0.3.0", + "_resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/run.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/run.js new file mode 100644 index 000000000..e717f02a3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/run.js @@ -0,0 +1,40 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + , timeout = 10000 + , fs = require('fs') + ; + +fs.readdir(__dirname, function (e, files) { + if (e) throw e + + var tests = files.filter(function (f) {return f.slice(0, 'test-'.length) === 'test-'}) + + var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + + var killed = false + var t = setTimeout(function () { + proc.kill() + exitCode += 1 + console.error(file + ' timeout') + killed = true + }, timeout) + + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + if (code && !killed) console.error(file + ' failed') + exitCode += code || 0 + clearTimeout(t) + next() + }) + } + next() + +}) + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js new file mode 100644 index 000000000..2cdc835bb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../index') + , assert = require('assert'); + +var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'Sid'); + +// test .value +assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js new file mode 100644 index 000000000..a33cfb232 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../index') + , Jar = Cookie.Jar + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/LICENSE new file mode 100644 index 000000000..a4a9aee0c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/README.md new file mode 100644 index 000000000..9d5b66343 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/README.md @@ -0,0 +1,4 @@ +forever-agent +============= + +HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/index.js new file mode 100644 index 000000000..5c07928ae --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/index.js @@ -0,0 +1,119 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = host + ':' + port + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + function onIdleError() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy() + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = host + ':' + port + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s) + if (index !== -1) { + this.sockets[name].splice(index, 1) + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name] + delete this.requests[name] + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free') + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + if (typeof port === 'object') { + options = port; + } else if (typeof host === 'object') { + options = host; + } else if (typeof options === 'object') { + options = options; + } else { + options = {}; + } + + if (typeof port === 'number') { + options.port = port; + } + + if (typeof host === 'string') { + options.host = host; + } + + return tls.connect(options); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/package.json new file mode 100644 index 000000000..2f7a995ce --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/forever-agent/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "forever-agent", + "description": "HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.", + "version": "0.5.0", + "repository": { + "url": "https://github.com/mikeal/forever-agent" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "forever-agent\n=============\n\nHTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mikeal/forever-agent/issues" + }, + "_id": "forever-agent@0.5.0", + "dist": { + "shasum": "69cf9e1f45985a385142175ec7d1668edbb2279f" + }, + "_from": "forever-agent@~0.5.0", + "_resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/License b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/License new file mode 100644 index 000000000..c7ff12a2f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/License @@ -0,0 +1,19 @@ +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/Readme.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/Readme.md new file mode 100644 index 000000000..dc73c463d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/Readme.md @@ -0,0 +1,163 @@ +# Form-Data [![Build Status](https://travis-ci.org/felixge/node-form-data.png?branch=master)](https://travis-ci.org/felixge/node-form-data) [![Dependency Status](https://gemnasium.com/felixge/node-form-data.png)](https://gemnasium.com/felixge/node-form-data) + +A module to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications. + +The API of this module is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd]. + +[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface +[streams2-thing]: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions + +## Install + +``` +npm install form-data +``` + +## Usage + +In this example we are constructing a form with 3 fields that contain a string, +a buffer and a file stream. + +``` javascript +var FormData = require('form-data'); +var fs = require('fs'); + +var form = new FormData(); +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_file', fs.createReadStream('/foo/bar.jpg')); +``` + +Also you can use http-response stream: + +``` javascript +var FormData = require('form-data'); +var http = require('http'); + +var form = new FormData(); + +http.request('http://nodejs.org/images/logo.png', function(response) { + form.append('my_field', 'my value'); + form.append('my_buffer', new Buffer(10)); + form.append('my_logo', response); +}); +``` + +Or @mikeal's request stream: + +``` javascript +var FormData = require('form-data'); +var request = require('request'); + +var form = new FormData(); + +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_logo', request('http://nodejs.org/images/logo.png')); +``` + +In order to submit this form to a web application, call ```submit(url, [callback])``` method: + +``` javascript +form.submit('http://example.org/', function(err, res) { + // res – response object (http.IncomingMessage) // + res.resume(); // for node-0.10.x +}); + +``` + +For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods. + +### Alternative submission methods + +You can use node's http client interface: + +``` javascript +var http = require('http'); + +var request = http.request({ + method: 'post', + host: 'example.org', + path: '/upload', + headers: form.getHeaders() +}); + +form.pipe(request); + +request.on('response', function(res) { + console.log(res.statusCode); +}); +``` + +Or if you would prefer the `'Content-Length'` header to be set for you: + +``` javascript +form.submit('example.org/upload', function(err, res) { + console.log(res.statusCode); +}); +``` + +To use custom headers and pre-known length in parts: + +``` javascript +var CRLF = '\r\n'; +var form = new FormData(); + +var options = { + header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF, + knownLength: 1 +}; + +form.append('my_buffer', buffer, options); + +form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); +}); +``` + +Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually: + +``` javascript +someModule.stream(function(err, stdout, stderr) { + if (err) throw err; + + var form = new FormData(); + + form.append('file', stdout, { + filename: 'unicycle.jpg', + contentType: 'image/jpg', + knownLength: 19806 + }); + + form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); + }); +}); +``` + +For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter: + +``` javascript +form.submit({ + host: 'example.com', + path: '/probably.php?extra=params', + auth: 'username:password' +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +## Notes + +- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround. +- If it feels like FormData hangs after submit and you're on ```node-0.10```, please check [Compatibility with Older Node Versions][streams2-thing] + +## TODO + +- Add new streams (0.10) support and try really hard not to break it for 0.8.x. + +## License + +Form-Data is licensed under the MIT license. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/lib/form_data.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/lib/form_data.js new file mode 100644 index 000000000..d1064748b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/lib/form_data.js @@ -0,0 +1,325 @@ +var CombinedStream = require('combined-stream'); +var util = require('util'); +var path = require('path'); +var http = require('http'); +var https = require('https'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var mime = require('mime'); +var async = require('async'); + +module.exports = FormData; +function FormData() { + this._overheadLength = 0; + this._valueLength = 0; + this._lengthRetrievers = []; + + CombinedStream.call(this); +} +util.inherits(FormData, CombinedStream); + +FormData.LINE_BREAK = '\r\n'; + +FormData.prototype.append = function(field, value, options) { + options = options || {}; + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') value = ''+value; + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(field, value, options); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) { + return; + } + + // no need to bother with the length + if (!options.knownLength) + this._lengthRetrievers.push(function(next) { + + if (value.hasOwnProperty('fd')) { + fs.stat(value.path, function(err, stat) { + if (err) { + next(err); + return; + } + + next(null, stat.size); + }); + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + next(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + next(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + next('Unknown stream'); + } + }); +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + var boundary = this.getBoundary(); + var header = ''; + + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (options.header != null) { + header = options.header; + } else { + header += '--' + boundary + FormData.LINE_BREAK + + 'Content-Disposition: form-data; name="' + field + '"'; + + // fs- and request- streams have path property + // or use custom filename and/or contentType + // TODO: Use request's response mime-type + if (options.filename || value.path) { + header += + '; filename="' + path.basename(options.filename || value.path) + '"' + FormData.LINE_BREAK + + 'Content-Type: ' + (options.contentType || mime.lookup(options.filename || value.path)); + + // http response has not + } else if (value.readable && value.hasOwnProperty('httpVersion')) { + header += + '; filename="' + path.basename(value.client._httpMessage.path) + '"' + FormData.LINE_BREAK + + 'Content-Type: ' + value.headers['content-type']; + } + + header += FormData.LINE_BREAK + FormData.LINE_BREAK; + } + + return header; +}; + +FormData.prototype._multiPartFooter = function(field, value, options) { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--'; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (var header in userHeaders) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + + return formHeaders; +} + +FormData.prototype.getCustomHeaders = function(contentType) { + contentType = contentType ? contentType : 'multipart/form-data'; + + var formHeaders = { + 'content-type': contentType + '; boundary=' + this.getBoundary(), + 'content-length': this.getLengthSync() + }; + + return formHeaders; +} + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function(debug) { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/felixge/node-form-data/issues/40 + if (this._lengthRetrievers.length) { + // Some async length retrivers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._lengthRetrievers.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + async.parallel(this._lengthRetrievers, function(err, values) { + if (err) { + cb(err); + return; + } + + values.forEach(function(length) { + knownLength += length; + }); + + cb(null, knownLength); + }); +}; + +FormData.prototype.submit = function(params, cb) { + + var request + , options + , defaults = { + method : 'post', + headers: this.getHeaders() + }; + + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { + params = parseUrl(params); + + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname + }, defaults); + } + else // use custom params + { + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; + } + } + + // https if specified, fallback to http in any other case + if (params.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + + // TODO: Add chunked encoding when no length (if err) + + // add content length + request.setHeader('Content-Length', length); + + this.pipe(request); + if (cb) { + request.on('error', cb); + request.on('response', cb.bind(this, null)); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (this.error) return; + + this.error = err; + this.pause(); + this.emit('error', err); +}; + +/* + * Santa's little helpers + */ + +// populates missing values +function populate(dst, src) { + for (var prop in src) { + if (!dst[prop]) dst[prop] = src[prop]; + } + return dst; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/LICENSE new file mode 100644 index 000000000..b7f9d5001 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/README.md new file mode 100644 index 000000000..9ff1acfdf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/README.md @@ -0,0 +1,1414 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. Also supports [component](https://github.com/component/component). + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about bind, not about async. If you are wondering how to +make async execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [forever](#forever) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then it's probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, callback) + +Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. +If an error is passed to fn's callback then 'callback' is called with the +error, otherwise it will never be called. + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as applyEach only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing an array of + queued tasks, which must call its callback(err) argument when finished, with + an optional error as an argument. +* payload - An optional integer for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8'); +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. It's also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/component.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/component.json new file mode 100644 index 000000000..bbb011548 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/component.json @@ -0,0 +1,11 @@ +{ + "name": "async", + "repo": "caolan/async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.1.23", + "keywords": [], + "dependencies": {}, + "development": {}, + "main": "lib/async.js", + "scripts": [ "lib/async.js" ] +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js new file mode 100755 index 000000000..cb6320d6a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js @@ -0,0 +1,955 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = setImmediate; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n queued tasks, which must call its callback(err) argument when finished, with \n an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8');\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", + "_id": "async@0.2.9", + "dist": { + "shasum": "93885d93f14550270027c9fd4ee106d88eb20b66" + }, + "_from": "async@~0.2.9", + "_resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore new file mode 100644 index 000000000..aba34f012 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore @@ -0,0 +1,3 @@ +*.un~ +/node_modules +/test/tmp diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/License b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/License new file mode 100644 index 000000000..4804b7ab4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile new file mode 100644 index 000000000..b4ff85a33 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md new file mode 100644 index 000000000..1a9999eb0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md @@ -0,0 +1,132 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = true + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = 2 * 1024 * 1024 + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = 0 + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 000000000..32849fd10 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,185 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + stream.on('data', this._checkDataSize.bind(this)); + + stream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)) + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore new file mode 100644 index 000000000..2fedb26cc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore @@ -0,0 +1,2 @@ +*.un~ +/node_modules/* diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License new file mode 100644 index 000000000..4804b7ab4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile new file mode 100644 index 000000000..b4ff85a33 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md new file mode 100644 index 000000000..5cb5b35e5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md @@ -0,0 +1,154 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 000000000..7c10d4825 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,99 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +DelayedStream.prototype.__defineGetter__('readable', function() { + return this.source.readable; +}); + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json new file mode 100644 index 000000000..d37600f1f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json @@ -0,0 +1,35 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "version": "0.0.5", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + }, + "readme": "# delayed-stream\n\nBuffers events from a stream until you are ready to handle them.\n\n## Installation\n\n``` bash\nnpm install delayed-stream\n```\n\n## Usage\n\nThe following example shows how to write a http echo server that delays its\nresponse by 1000 ms.\n\n``` javascript\nvar DelayedStream = require('delayed-stream');\nvar http = require('http');\n\nhttp.createServer(function(req, res) {\n var delayed = DelayedStream.create(req);\n\n setTimeout(function() {\n res.writeHead(200);\n delayed.pipe(res);\n }, 1000);\n});\n```\n\nIf you are not using `Stream#pipe`, you can also manually release the buffered\nevents by calling `delayedStream.resume()`:\n\n``` javascript\nvar delayed = DelayedStream.create(req);\n\nsetTimeout(function() {\n // Emit all buffered events and resume underlaying source\n delayed.resume();\n}, 1000);\n```\n\n## Implementation\n\nIn order to use this meta stream properly, here are a few things you should\nknow about the implementation.\n\n### Event Buffering / Proxying\n\nAll events of the `source` stream are hijacked by overwriting the `source.emit`\nmethod. Until node implements a catch-all event listener, this is the only way.\n\nHowever, delayed-stream still continues to emit all events it captures on the\n`source`, regardless of whether you have released the delayed stream yet or\nnot.\n\nUpon creation, delayed-stream captures all `source` events and stores them in\nan internal event buffer. Once `delayedStream.release()` is called, all\nbuffered events are emitted on the `delayedStream`, and the event buffer is\ncleared. After that, delayed-stream merely acts as a proxy for the underlaying\nsource.\n\n### Error handling\n\nError events on `source` are buffered / proxied just like any other events.\nHowever, `delayedStream.create` attaches a no-op `'error'` listener to the\n`source`. This way you only have to handle errors on the `delayedStream`\nobject, rather than in two places.\n\n### Buffer limits\n\ndelayed-stream provides a `maxDataSize` property that can be used to limit\nthe amount of data being buffered. In order to protect you from bad `source`\nstreams that don't react to `source.pause()`, this feature is enabled by\ndefault.\n\n## API\n\n### DelayedStream.create(source, [options])\n\nReturns a new `delayedStream`. Available options are:\n\n* `pauseStream`\n* `maxDataSize`\n\nThe description for those properties can be found below.\n\n### delayedStream.source\n\nThe `source` stream managed by this object. This is useful if you are\npassing your `delayedStream` around, and you still want to access properties\non the `source` object.\n\n### delayedStream.pauseStream = true\n\nWhether to pause the underlaying `source` when calling\n`DelayedStream.create()`. Modifying this property afterwards has no effect.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature. You can also modify this property during runtime.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature.\n\n### delayedStream.dataSize = 0\n\nThe amount of data buffered so far.\n\n### delayedStream.readable\n\nAn ECMA5 getter that returns the value of `source.readable`.\n\n### delayedStream.resume()\n\nIf the `delayedStream` has not been released so far, `delayedStream.release()`\nis called.\n\nIn either case, `source.resume()` is called.\n\n### delayedStream.pause()\n\nCalls `source.pause()`.\n\n### delayedStream.pipe(dest)\n\nCalls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.\n\n### delayedStream.release()\n\nEmits and clears all events that have been buffered up so far. This does not\nresume the underlaying source, use `delayedStream.resume()` instead.\n\n## License\n\ndelayed-stream is licensed under the MIT license.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/felixge/node-delayed-stream/issues" + }, + "_id": "delayed-stream@0.0.5", + "dist": { + "shasum": "087ac89b707b26bfca4c987bdb569427db1b262e" + }, + "_from": "delayed-stream@0.0.5", + "_resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js new file mode 100644 index 000000000..4d71b8a64 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js @@ -0,0 +1,6 @@ +var common = module.exports; + +common.DelayedStream = require('..'); +common.assert = require('assert'); +common.fake = require('fake'); +common.PORT = 49252; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js new file mode 100644 index 000000000..9ecad5b8a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var DelayedStream = common.DelayedStream; +var http = require('http'); + +var UPLOAD = new Buffer(10 * 1024 * 1024); + +var server = http.createServer(function(req, res) { + var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length}); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 10); +}); +server.listen(common.PORT, function() { + var request = http.request({ + method: 'POST', + port: common.PORT, + }); + + request.write(UPLOAD); + request.end(); + + request.on('response', function(res) { + var received = 0; + res + .on('data', function(chunk) { + received += chunk.length; + }) + .on('end', function() { + assert.equal(received, UPLOAD.length); + server.close(); + }); + }); +}); + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js new file mode 100644 index 000000000..6f417f3e9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js @@ -0,0 +1,21 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testAutoPause() { + var source = new Stream(); + + fake.expect(source, 'pause', 1); + var delayedStream = DelayedStream.create(source); + fake.verify(); +})(); + +(function testDisableAutoPause() { + var source = new Stream(); + fake.expect(source, 'pause', 0); + + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + fake.verify(); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js new file mode 100644 index 000000000..b50c39783 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js @@ -0,0 +1,14 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(source, 'pause'); + delayedStream.pause(); + fake.verify(); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js new file mode 100644 index 000000000..fc4047e08 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js @@ -0,0 +1,48 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // delayedStream must not emit until we resume + fake.expect(delayedStream, 'emit', 0); + + // but our original source must emit + var params = []; + source.on('foo', function(param) { + params.push(param); + }); + + source.emit('foo', 1); + source.emit('foo', 2); + + // Make sure delayedStream did not emit, and source did + assert.deepEqual(params, [1, 2]); + fake.verify(); + + // After resume, delayedStream must playback all events + fake + .stub(delayedStream, 'emit') + .times(Infinity) + .withArg(1, 'newListener'); + fake.expect(delayedStream, 'emit', ['foo', 1]); + fake.expect(delayedStream, 'emit', ['foo', 2]); + fake.expect(source, 'resume'); + + delayedStream.resume(); + fake.verify(); + + // Calling resume again will delegate to source + fake.expect(source, 'resume'); + delayedStream.resume(); + fake.verify(); + + // Emitting more events directly leads to them being emitted + fake.expect(delayedStream, 'emit', ['foo', 3]); + source.emit('foo', 3); + fake.verify(); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js new file mode 100644 index 000000000..a9d35e72c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js @@ -0,0 +1,15 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testHandleSourceErrors() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // We deal with this by attaching a no-op listener to 'error' on the source + // when creating a new DelayedStream. This way error events on the source + // won't throw. + source.emit('error', new Error('something went wrong')); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js new file mode 100644 index 000000000..7638a2bf0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testMaxDataSize() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false}); + + source.emit('data', new Buffer(1024)); + + fake + .expect(delayedStream, 'emit') + .withArg(1, 'error'); + source.emit('data', new Buffer(1)); + fake.verify(); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js new file mode 100644 index 000000000..7d312ab1f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testPipeReleases() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(delayedStream, 'resume'); + delayedStream.pipe(new Stream()); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js new file mode 100644 index 000000000..d436163b7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testProxyReadableProperty() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + source.readable = fake.value('source.readable'); + assert.strictEqual(delayedStream.readable, source.readable); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js new file mode 100755 index 000000000..0bb8e8224 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json new file mode 100644 index 000000000..cf62d05d7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json @@ -0,0 +1,36 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "0.0.4", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "engines": { + "node": "*" + }, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "devDependencies": { + "far": "0.0.1" + }, + "readme": "# combined-stream\n\nA stream that emits multiple other streams one after another.\n\n## Installation\n\n``` bash\nnpm install combined-stream\n```\n\n## Usage\n\nHere is a simple example that shows how you can use combined-stream to combine\ntwo files into one:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nWhile the example above works great, it will pause all source streams until\nthey are needed. If you don't want that to happen, you can set `pauseStreams`\nto `false`:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create({pauseStreams: false});\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nHowever, what if you don't have all the source streams yet, or you don't want\nto allocate the resources (file descriptors, memory, etc.) for them right away?\nWell, in that case you can simply provide a callback that supplies the stream\nby calling a `next()` function:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(function(next) {\n next(fs.createReadStream('file1.txt'));\n});\ncombinedStream.append(function(next) {\n next(fs.createReadStream('file2.txt'));\n});\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\n## API\n\n### CombinedStream.create([options])\n\nReturns a new combined stream object. Available options are:\n\n* `maxDataSize`\n* `pauseStreams`\n\nThe effect of those options is described below.\n\n### combinedStream.pauseStreams = true\n\nWhether to apply back pressure to the underlaying streams. If set to `false`,\nthe underlaying streams will never be paused. If set to `true`, the\nunderlaying streams will be paused right after being appended, as well as when\n`delayedStream.pipe()` wants to throttle.\n\n### combinedStream.maxDataSize = 2 * 1024 * 1024\n\nThe maximum amount of bytes (or characters) to buffer for all source streams.\nIf this value is exceeded, `combinedStream` emits an `'error'` event.\n\n### combinedStream.dataSize = 0\n\nThe amount of bytes (or characters) currently buffered by `combinedStream`.\n\n### combinedStream.append(stream)\n\nAppends the given `stream` to the combinedStream object. If `pauseStreams` is\nset to `true, this stream will also be paused right away.\n\n`streams` can also be a function that takes one parameter called `next`. `next`\nis a function that must be invoked in order to provide the `next` stream, see\nexample above.\n\nRegardless of how the `stream` is appended, combined-stream always attaches an\n`'error'` listener to it, so you don't have to do that manually.\n\nSpecial case: `stream` can also be a String or Buffer.\n\n### combinedStream.write(data)\n\nYou should not call this, `combinedStream` takes care of piping the appended\nstreams into itself for you.\n\n### combinedStream.resume()\n\nCauses `combinedStream` to start drain the streams it manages. The function is\nidempotent, and also emits a `'resume'` event each time which usually goes to\nthe stream that is currently being drained.\n\n### combinedStream.pause();\n\nIf `combinedStream.pauseStreams` is set to `false`, this does nothing.\nOtherwise a `'pause'` event is emitted, this goes to the stream that is\ncurrently being drained, so you can use it to apply back pressure.\n\n### combinedStream.end();\n\nSets `combinedStream.writable` to false, emits an `'end'` event, and removes\nall streams from the queue.\n\n### combinedStream.destroy();\n\nSame as `combinedStream.end()`, except it emits a `'close'` event instead of\n`'end'`.\n\n## License\n\ncombined-stream is licensed under the MIT license.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/felixge/node-combined-stream/issues" + }, + "_id": "combined-stream@0.0.4", + "dist": { + "shasum": "256da4fb60fc8ebe526490eff9cad450c43fea1a" + }, + "_from": "combined-stream@~0.0.4", + "_resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.4.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js new file mode 100644 index 000000000..81543485e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js @@ -0,0 +1,23 @@ +var common = module.exports; + +var path = require('path'); +var fs = require('fs'); +var root = path.join(__dirname, '..'); + +common.dir = { + fixture: root + '/test/fixture', + tmp: root + '/test/tmp', +}; + +// Create tmp directory if it does not exist +// Not using fs.exists so as to be node 0.6.x compatible +try { + fs.statSync(common.dir.tmp); +} +catch (e) { + // Dir does not exist + fs.mkdirSync(common.dir.tmp); +} + +common.CombinedStream = require(root); +common.assert = require('assert'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt new file mode 100644 index 000000000..50e0218df --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt @@ -0,0 +1,256 @@ +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt new file mode 100644 index 000000000..da1d821fe --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt @@ -0,0 +1,256 @@ +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js new file mode 100644 index 000000000..44ecabab6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js @@ -0,0 +1,27 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE1)); + }); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE2)); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js new file mode 100644 index 000000000..e3fbd1842 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js @@ -0,0 +1,34 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; + +(function testDataSizeGetter() { + var combinedStream = CombinedStream.create(); + + assert.strictEqual(combinedStream.dataSize, 0); + + // Test one stream + combinedStream._streams.push({dataSize: 10}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 10); + + // Test two streams + combinedStream._streams.push({dataSize: 23}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test currentStream + combinedStream._currentStream = {dataSize: 20}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 53); + + // Test currentStream without dataSize + combinedStream._currentStream = {}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test stream function + combinedStream._streams.push(function() {}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js new file mode 100644 index 000000000..c678575c0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var BUFFER = new Buffer('Bacon is delicious'); +var FILE2 = common.dir.fixture + '/file2.txt'; +var STRING = 'The € kicks the $\'s ass!'; + +var EXPECTED = + fs.readFileSync(FILE1) + + BUFFER + + fs.readFileSync(FILE2) + + STRING; +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(BUFFER); + combinedStream.append(fs.createReadStream(FILE2)); + combinedStream.append(function(next) { + next(STRING); + }); + + var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js new file mode 100644 index 000000000..263cfdf72 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js @@ -0,0 +1,35 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.equal(stream2.dataSize, 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + console.error(GOT.length, EXPECTED.length); + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js new file mode 100644 index 000000000..c3d288d01 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js @@ -0,0 +1,39 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var util = require('util'); +var Stream = require('stream').Stream; + +var s = CombinedStream.create(); + + +function StringStream(){ + this.writable=true; + this.str="" +} +util.inherits(StringStream,Stream); + +StringStream.prototype.write=function(chunk,encoding){ + this.str+=chunk.toString(); + this.emit('data',chunk); +} + +StringStream.prototype.end=function(chunk,encoding){ + this.emit('end'); +} + +StringStream.prototype.toString=function(){ + return this.str; +} + + +s.append("foo."); +s.append(""); +s.append("bar"); + +var ss = new StringStream(); + +s.pipe(ss); +s.resume(); + +assert.equal(ss.toString(),"foo.bar"); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js new file mode 100644 index 000000000..aefa36e6b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js @@ -0,0 +1,17 @@ +var fs = require('fs'); +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var FILE1 = common.dir.fixture + '/file1.txt'; +var fileStream = fs.createReadStream(FILE1); + +var foo = function(){}; + +(function testIsStreamLike() { + assert(! CombinedStream.isStreamLike(true)); + assert(! CombinedStream.isStreamLike("I am a string")); + assert(! CombinedStream.isStreamLike(7)); + assert(! CombinedStream.isStreamLike(foo)); + + assert(CombinedStream.isStreamLike(fileStream)); +})(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js new file mode 100644 index 000000000..25f47a47c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js @@ -0,0 +1,24 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var gotErr = null; + combinedStream.on('error', function(err) { + gotErr = err; + }); + + process.on('exit', function() { + assert.ok(gotErr); + assert.ok(gotErr.message.match(/bytes/)); + }); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js new file mode 100644 index 000000000..30a3a6f84 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js @@ -0,0 +1,30 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.ok(stream2.dataSize > 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js new file mode 100755 index 000000000..0bb8e8224 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/package.json new file mode 100644 index 000000000..ea654cb24 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/form-data/package.json @@ -0,0 +1,49 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "form-data", + "description": "A module to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", + "version": "0.1.2", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-form-data.git" + }, + "main": "./lib/form_data", + "scripts": { + "test": "node test/run.js" + }, + "engines": { + "node": ">= 0.6" + }, + "dependencies": { + "combined-stream": "~0.0.4", + "mime": "~1.2.11", + "async": "~0.2.9" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/felixge/node-form-data/master/License" + } + ], + "devDependencies": { + "fake": "~0.2.2", + "far": "~0.0.7", + "formidable": "~1.0.14", + "request": "~2.27.0" + }, + "readme": "# Form-Data [![Build Status](https://travis-ci.org/felixge/node-form-data.png?branch=master)](https://travis-ci.org/felixge/node-form-data) [![Dependency Status](https://gemnasium.com/felixge/node-form-data.png)](https://gemnasium.com/felixge/node-form-data)\n\nA module to create readable ```\"multipart/form-data\"``` streams. Can be used to submit forms and file uploads to other web applications.\n\nThe API of this module is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd].\n\n[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface\n[streams2-thing]: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions\n\n## Install\n\n```\nnpm install form-data\n```\n\n## Usage\n\nIn this example we are constructing a form with 3 fields that contain a string,\na buffer and a file stream.\n\n``` javascript\nvar FormData = require('form-data');\nvar fs = require('fs');\n\nvar form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n```\n\nAlso you can use http-response stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar http = require('http');\n\nvar form = new FormData();\n\nhttp.request('http://nodejs.org/images/logo.png', function(response) {\n form.append('my_field', 'my value');\n form.append('my_buffer', new Buffer(10));\n form.append('my_logo', response);\n});\n```\n\nOr @mikeal's request stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar request = require('request');\n\nvar form = new FormData();\n\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_logo', request('http://nodejs.org/images/logo.png'));\n```\n\nIn order to submit this form to a web application, call ```submit(url, [callback])``` method:\n\n``` javascript\nform.submit('http://example.org/', function(err, res) {\n // res – response object (http.IncomingMessage) //\n res.resume(); // for node-0.10.x\n});\n\n```\n\nFor more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods.\n\n### Alternative submission methods\n\nYou can use node's http client interface:\n\n``` javascript\nvar http = require('http');\n\nvar request = http.request({\n method: 'post',\n host: 'example.org',\n path: '/upload',\n headers: form.getHeaders()\n});\n\nform.pipe(request);\n\nrequest.on('response', function(res) {\n console.log(res.statusCode);\n});\n```\n\nOr if you would prefer the `'Content-Length'` header to be set for you:\n\n``` javascript\nform.submit('example.org/upload', function(err, res) {\n console.log(res.statusCode);\n});\n```\n\nTo use custom headers and pre-known length in parts:\n\n``` javascript\nvar CRLF = '\\r\\n';\nvar form = new FormData();\n\nvar options = {\n header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,\n knownLength: 1\n};\n\nform.append('my_buffer', buffer, options);\n\nform.submit('http://example.com/', function(err, res) {\n if (err) throw err;\n console.log('Done');\n});\n```\n\nForm-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide \"file\"-related information manually:\n\n``` javascript\nsomeModule.stream(function(err, stdout, stderr) {\n if (err) throw err;\n\n var form = new FormData();\n\n form.append('file', stdout, {\n filename: 'unicycle.jpg',\n contentType: 'image/jpg',\n knownLength: 19806\n });\n\n form.submit('http://example.com/', function(err, res) {\n if (err) throw err;\n console.log('Done');\n });\n});\n```\n\nFor edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:\n\n``` javascript\nform.submit({\n host: 'example.com',\n path: '/probably.php?extra=params',\n auth: 'username:password'\n}, function(err, res) {\n console.log(res.statusCode);\n});\n```\n\n## Notes\n\n- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround.\n- If it feels like FormData hangs after submit and you're on ```node-0.10```, please check [Compatibility with Older Node Versions][streams2-thing]\n\n## TODO\n\n- Add new streams (0.10) support and try really hard not to break it for 0.8.x.\n\n## License\n\nForm-Data is licensed under the MIT license.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/felixge/node-form-data/issues" + }, + "_id": "form-data@0.1.2", + "dist": { + "shasum": "96ec74067f195ad2a027f2b7b9605037fc18da61" + }, + "_from": "form-data@~0.1.0", + "_resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.2.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.npmignore new file mode 100644 index 000000000..77ba16cb0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.npmignore @@ -0,0 +1,18 @@ +.idea +*.iml +npm-debug.log +dump.rdb +node_modules +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.travis.yml b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.travis.yml new file mode 100755 index 000000000..047f7e3d5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/.travis.yml @@ -0,0 +1,5 @@ +language: node_js + +node_js: + - 0.10 + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/LICENSE new file mode 100755 index 000000000..e699a7bdb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2012-2013, Eran Hammer. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Eran Hammer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 ERAN HAMMER 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. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/Makefile b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/Makefile new file mode 100755 index 000000000..5f339bf34 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/Makefile @@ -0,0 +1,10 @@ +test: + @node node_modules/lab/bin/lab +test-cov: + @node node_modules/lab/bin/lab -r threshold -t 100 +test-cov-html: + @node node_modules/lab/bin/lab -r html -o coverage.html +complexity: + @node node_modules/complexity-report/src/cli.js -o complexity.md -f markdown lib + +.PHONY: test test-cov test-cov-html complexity diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/README.md new file mode 100755 index 000000000..010bac6d0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/hawk/README.md @@ -0,0 +1,627 @@ +![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png) + + **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial +HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz). + +Current version: **1.0** + +[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk) + +# Table of Content + +- [**Introduction**](#introduction) + - [Replay Protection](#replay-protection) + - [Usage Example](#usage-example) + - [Protocol Example](#protocol-example) + - [Payload Validation](#payload-validation) + - [Response Payload Validation](#response-payload-validation) + - [Browser Support and Considerations](#browser-support-and-considerations) +

    +- [**Single URI Authorization**](#single-uri-authorization) + - [Usage Example](#bewit-usage-example) +

    +- [**Security Considerations**](#security-considerations) + - [MAC Keys Transmission](#mac-keys-transmission) + - [Confidentiality of Requests](#confidentiality-of-requests) + - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers) + - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials) + - [Entropy of Keys](#entropy-of-keys) + - [Coverage Limitations](#coverage-limitations) + - [Future Time Manipulation](#future-time-manipulation) + - [Client Clock Poisoning](#client-clock-poisoning) + - [Bewit Limitations](#bewit-limitations) + - [Host Header Forgery](#host-header-forgery) +

    +- [**Frequently Asked Questions**](#frequently-asked-questions) +

    +- [**Acknowledgements**](#acknowledgements) + +# Introduction + +**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with +partial cryptographic verification of the request and response, covering the HTTP method, request URI, host, +and optionally the request payload. + +Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of +client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme, +the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is +included in its place. + +However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of +replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less +"chattiness" (interaction with the server). + +Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because +the client and server must both have access to the key material in the clear. + +The primary design goals of this scheme are to: +* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources, +* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where + to send an authenticated request), and +* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client + failure to validate the server's identity as part of its TLS handshake. + +In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using +a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk). + +The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server, +which is beyond the scope of this module. Typically, the shared credentials are established via an initial +TLS-protected phase or derived from some other shared confidential information available to both the client +and the server. + + +## Replay Protection + +Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more +than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when +making requests. This gives the server enough information to prevent replay attacks. + +The nonce is generated by the client, and is a string unique across all requests with the same timestamp and +key identifier combination. + +The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards +are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks. +By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in +practice translates to a maximum of 2 minutes as the skew can be positive or negative). + +Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client +clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types +(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response +to a bad timestamp. + +There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a +potential attack vector). Instead, the client only uses the server's time to calculate an offset used only +for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing +the number of round trips required to authenticate the first request. + + +## Usage Example + +Server code: + +```javascript +var Http = require('http'); +var Hawk = require('hawk'); + + +// Credentials lookup function + +var credentialsFunc = function (id, callback) { + + var credentials = { + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'Steve' + }; + + return callback(null, credentials); +}; + +// Create HTTP server + +var handler = function (req, res) { + + // Authenticate incoming request + + Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + + // Prepare response + + var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!'); + var headers = { 'Content-Type': 'text/plain' }; + + // Generate Server-Authorization response header + + var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] }); + headers['Server-Authorization'] = header; + + // Send the response back + + res.writeHead(!err ? 200 : 401, headers); + res.end(payload); + }); +}; + +// Start server + +Http.createServer(handler).listen(8000, 'example.com'); +``` + +Client code: + +```javascript +var Request = require('request'); +var Hawk = require('hawk'); + + +// Client credentials + +var credentials = { + id: 'dh37fgj492je', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256' +} + +// Request options + +var requestOptions = { + uri: 'http://example.com:8000/resource/1?b=1&a=2', + method: 'GET', + headers: {} +}; + +// Generate Authorization request header + +var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' }); +requestOptions.headers.Authorization = header.field; + +// Send authenticated request + +Request(requestOptions, function (error, response, body) { + + // Authenticate the server's response + + var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body }); + + // Output results + + console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)')); +}); +``` + +**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local +machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method. + +```javascript +Hawk.sntp.start(); +``` + + +## Protocol Example + +The client attempts to access a protected resource without authentication, sending the following HTTP request to +the resource server: + +``` +GET /resource/1?b=1&a=2 HTTP/1.1 +Host: example.com:8000 +``` + +The resource server returns an authentication challenge. + +``` +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Hawk +``` + +The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/" +server. The **Hawk** credentials issued to the client include the following attributes: + +* Key identifier: dh37fgj492je +* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn +* Algorithm: sha256 + +The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1, +1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline +character): + +``` +hawk.1.header +1353832234 +j4h3g2 +GET +/resource/1?b=1&a=2 +example.com +8000 + +some-app-ext-data + +``` + +The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string. +The result is base64-encoded to produce the request MAC: + +``` +6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE= +``` + +The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using +the HTTP `Authorization` request header field: + +``` +GET /resource/1?b=1&a=2 HTTP/1.1 +Host: example.com:8000 +Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=" +``` + +The server validates the request by calculating the request MAC again based on the request received and verifies the validity +and scope of the **Hawk** credentials. If valid, the server responds with the requested resource. + + +### Payload Validation + +**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash +using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character): +* `hawk.1.payload` +* the content-type in lowercase, without any parameters (e.g. `application/json`) +* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability) + +For example: + +* Payload: `Thank you for flying Hawk` +* Content Type: `text/plain` +* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=` + +Results in the following input to the payload hash function (newline terminated values): + +``` +hawk.1.payload +text/plain +Thank you for flying Hawk + +``` + +Which produces the following hash value: + +``` +Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY= +``` + +The client constructs the normalized request string (newline terminated values): + +``` +hawk.1.header +1353832234 +j4h3g2 +POST +/resource/1?a=1&b=2 +example.com +8000 +Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY= +some-app-ext-data + +``` + +Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data, +and request MAC, with the request using the HTTP `Authorization` request header field: + +``` +POST /resource/1?a=1&b=2 HTTP/1.1 +Host: example.com:8000 +Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw=" +``` + +It is up to the server if and when it validates the payload for any given request, based solely on it's security policy +and the nature of the data included. + +If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct +the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value +with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash. + +However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed +at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value +provided by the client after validating the MAC. + +It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value +included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided +by the client, the payload may be modified by an attacker. + + +## Response Payload Validation + +**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the +client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header +as a response header using the exact same syntax as the `Authorization` request header field. + +The header is contructed using the same process as the client's request header. The server uses the same credentials and other +artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with +new values based on the server response. The rest as identical to those used by the client. + +The result MAC digest is included with the optional `hash` and `ext` values: + +``` +Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific" +``` + + +## Browser Support and Considerations + +A browser script is provided for including using a `')); + expect(boom.response.payload.message).to.not.contain(''); + expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); + done(); + }); + + it('encodes \' characters', function (done) { + + var encoded = Hoek.escapeJavaScript('something(\'param\')'); + expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); + done(); + }); + + it('encodes large unicode characters with the correct padding', function (done) { + + var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); + expect(encoded).to.equal('\\u0500\\u1000'); + done(); + }); + + it('doesn\'t throw an exception when passed null', function (done) { + + var encoded = Hoek.escapeJavaScript(null); + expect(encoded).to.equal(''); + done(); + }); + }); + + describe('#escapeHtml', function () { + + it('encodes / characters', function (done) { + + var encoded = Hoek.escapeHtml(''); + expect(encoded).to.equal('<script>alert(1)</script>'); + done(); + }); + + it('encodes < and > as named characters', function (done) { + + var encoded = Hoek.escapeHtml(' +``` + +Or in node.js: + +``` +npm install node-uuid +``` + +```javascript +var uuid = require('node-uuid'); +``` + +Then create some ids ... + +```javascript +// Generate a v1 (time-based) id +uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' + +// Generate a v4 (random) id +uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' +``` + +## API + +### uuid.v1([`options` [, `buffer` [, `offset`]]]) + +Generate and return a RFC4122 v1 (timestamp-based) UUID. + +* `options` - (Object) Optional uuid state to apply. Properties may include: + + * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID. See note 1. + * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence. Default: An internally maintained clockseq is used. + * `msecs` - (Number | Date) Time in milliseconds since unix Epoch. Default: The current time is used. + * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2. + +* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. +* `offset` - (Number) Starting index in `buffer` at which to begin writing. + +Returns `buffer`, if specified, otherwise the string form of the UUID + +Notes: + +1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.) + +Example: Generate string UUID with fully-specified options + +```javascript +uuid.v1({ + node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab], + clockseq: 0x1234, + msecs: new Date('2011-11-01').getTime(), + nsecs: 5678 +}); // -> "710b962e-041c-11e1-9234-0123456789ab" +``` + +Example: In-place generation of two binary IDs + +```javascript +// Generate two ids in an array +var arr = new Array(32); // -> [] +uuid.v1(null, arr, 0); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15] +uuid.v1(null, arr, 16); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15] + +// Optionally use uuid.unparse() to get stringify the ids +uuid.unparse(buffer); // -> '02a2ce90-1432-11e1-8558-0b488e4fc115' +uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115' +``` + +### uuid.v4([`options` [, `buffer` [, `offset`]]]) + +Generate and return a RFC4122 v4 UUID. + +* `options` - (Object) Optional uuid state to apply. Properties may include: + + * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values + * `rng` - (Function) Random # generator to use. Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values. + +* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. +* `offset` - (Number) Starting index in `buffer` at which to begin writing. + +Returns `buffer`, if specified, otherwise the string form of the UUID + +Example: Generate string UUID with fully-specified options + +```javascript +uuid.v4({ + random: [ + 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea, + 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36 + ] +}); +// -> "109156be-c4fb-41ea-b1b4-efe1671c5836" +``` + +Example: Generate two IDs in a single buffer + +```javascript +var buffer = new Array(32); // (or 'new Buffer' in node.js) +uuid.v4(null, buffer, 0); +uuid.v4(null, buffer, 16); +``` + +### uuid.parse(id[, buffer[, offset]]) +### uuid.unparse(buffer[, offset]) + +Parse and unparse UUIDs + + * `id` - (String) UUID(-like) string + * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used + * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0 + +Example parsing and unparsing a UUID string + +```javascript +var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> +var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10' +``` + +### uuid.noConflict() + +(Browsers only) Set `uuid` property back to it's previous value. + +Returns the node-uuid object. + +Example: + +```javascript +var myUuid = uuid.noConflict(); +myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' +``` + +## Deprecated APIs + +Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version. + +### uuid([format [, buffer [, offset]]]) + +uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary). + +### uuid.BufferClass + +The class of container created when generating binary uuid data if no buffer argument is specified. This is expected to go away, with no replacement API. + +## Testing + +In node.js + +``` +> cd test +> node test.js +``` + +In Browser + +``` +open test/test.html +``` + +### Benchmarking + +Requires node.js + +``` +npm install uuid uuid-js +node benchmark/benchmark.js +``` + +For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark) + +For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance). + +## Release notes + +### 1.4.0 + +* Improved module context detection +* Removed public RNG functions + +### 1.3.2 + +* Improve tests and handling of v1() options (Issue #24) +* Expose RNG option to allow for perf testing with different generators + +### 1.3.0 + +* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)! +* Support for node.js crypto API +* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/README.md new file mode 100644 index 000000000..aaeb2ea01 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/README.md @@ -0,0 +1,53 @@ +# node-uuid Benchmarks + +### Results + +To see the results of our benchmarks visit https://github.com/broofa/node-uuid/wiki/Benchmark + +### Run them yourself + +node-uuid comes with some benchmarks to measure performance of generating UUIDs. These can be run using node.js. node-uuid is being benchmarked against some other uuid modules, that are available through npm namely `uuid` and `uuid-js`. + +To prepare and run the benchmark issue; + +``` +npm install uuid uuid-js +node benchmark/benchmark.js +``` + +You'll see an output like this one: + +``` +# v4 +nodeuuid.v4(): 854700 uuids/second +nodeuuid.v4('binary'): 788643 uuids/second +nodeuuid.v4('binary', buffer): 1336898 uuids/second +uuid(): 479386 uuids/second +uuid('binary'): 582072 uuids/second +uuidjs.create(4): 312304 uuids/second + +# v1 +nodeuuid.v1(): 938086 uuids/second +nodeuuid.v1('binary'): 683060 uuids/second +nodeuuid.v1('binary', buffer): 1644736 uuids/second +uuidjs.create(1): 190621 uuids/second +``` + +* The `uuid()` entries are for Nikhil Marathe's [uuid module](https://bitbucket.org/nikhilm/uuidjs) which is a wrapper around the native libuuid library. +* The `uuidjs()` entries are for Patrick Negri's [uuid-js module](https://github.com/pnegri/uuid-js) which is a pure javascript implementation based on [UUID.js](https://github.com/LiosK/UUID.js) by LiosK. + +If you want to get more reliable results you can run the benchmark multiple times and write the output into a log file: + +``` +for i in {0..9}; do node benchmark/benchmark.js >> benchmark/bench_0.4.12.log; done; +``` + +If you're interested in how performance varies between different node versions, you can issue the above command multiple times. + +You can then use the shell script `bench.sh` provided in this directory to calculate the averages over all benchmark runs and draw a nice plot: + +``` +(cd benchmark/ && ./bench.sh) +``` + +This assumes you have [gnuplot](http://www.gnuplot.info/) and [ImageMagick](http://www.imagemagick.org/) installed. You'll find a nice `bench.png` graph in the `benchmark/` directory then. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu new file mode 100644 index 000000000..a342fbbe0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu @@ -0,0 +1,174 @@ +#!/opt/local/bin/gnuplot -persist +# +# +# G N U P L O T +# Version 4.4 patchlevel 3 +# last modified March 2011 +# System: Darwin 10.8.0 +# +# Copyright (C) 1986-1993, 1998, 2004, 2007-2010 +# Thomas Williams, Colin Kelley and many others +# +# gnuplot home: http://www.gnuplot.info +# faq, bugs, etc: type "help seeking-assistance" +# immediate help: type "help" +# plot window: hit 'h' +set terminal postscript eps noenhanced defaultplex \ + leveldefault color colortext \ + solid linewidth 1.2 butt noclip \ + palfuncparam 2000,0.003 \ + "Helvetica" 14 +set output 'bench.eps' +unset clip points +set clip one +unset clip two +set bar 1.000000 front +set border 31 front linetype -1 linewidth 1.000 +set xdata +set ydata +set zdata +set x2data +set y2data +set timefmt x "%d/%m/%y,%H:%M" +set timefmt y "%d/%m/%y,%H:%M" +set timefmt z "%d/%m/%y,%H:%M" +set timefmt x2 "%d/%m/%y,%H:%M" +set timefmt y2 "%d/%m/%y,%H:%M" +set timefmt cb "%d/%m/%y,%H:%M" +set boxwidth +set style fill empty border +set style rectangle back fc lt -3 fillstyle solid 1.00 border lt -1 +set style circle radius graph 0.02, first 0, 0 +set dummy x,y +set format x "% g" +set format y "% g" +set format x2 "% g" +set format y2 "% g" +set format z "% g" +set format cb "% g" +set angles radians +unset grid +set key title "" +set key outside left top horizontal Right noreverse enhanced autotitles columnhead nobox +set key noinvert samplen 4 spacing 1 width 0 height 0 +set key maxcolumns 2 maxrows 0 +unset label +unset arrow +set style increment default +unset style line +set style line 1 linetype 1 linewidth 2.000 pointtype 1 pointsize default pointinterval 0 +unset style arrow +set style histogram clustered gap 2 title offset character 0, 0, 0 +unset logscale +set offsets graph 0.05, 0.15, 0, 0 +set pointsize 1.5 +set pointintervalbox 1 +set encoding default +unset polar +unset parametric +unset decimalsign +set view 60, 30, 1, 1 +set samples 100, 100 +set isosamples 10, 10 +set surface +unset contour +set clabel '%8.3g' +set mapping cartesian +set datafile separator whitespace +unset hidden3d +set cntrparam order 4 +set cntrparam linear +set cntrparam levels auto 5 +set cntrparam points 5 +set size ratio 0 1,1 +set origin 0,0 +set style data points +set style function lines +set xzeroaxis linetype -2 linewidth 1.000 +set yzeroaxis linetype -2 linewidth 1.000 +set zzeroaxis linetype -2 linewidth 1.000 +set x2zeroaxis linetype -2 linewidth 1.000 +set y2zeroaxis linetype -2 linewidth 1.000 +set ticslevel 0.5 +set mxtics default +set mytics default +set mztics default +set mx2tics default +set my2tics default +set mcbtics default +set xtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set xtics norangelimit +set xtics () +set ytics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set ytics autofreq norangelimit +set ztics border in scale 1,0.5 nomirror norotate offset character 0, 0, 0 +set ztics autofreq norangelimit +set nox2tics +set noy2tics +set cbtics border in scale 1,0.5 mirror norotate offset character 0, 0, 0 +set cbtics autofreq norangelimit +set title "" +set title offset character 0, 0, 0 font "" norotate +set timestamp bottom +set timestamp "" +set timestamp offset character 0, 0, 0 font "" norotate +set rrange [ * : * ] noreverse nowriteback # (currently [8.98847e+307:-8.98847e+307] ) +set autoscale rfixmin +set autoscale rfixmax +set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] ) +set autoscale tfixmin +set autoscale tfixmax +set urange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale ufixmin +set autoscale ufixmax +set vrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale vfixmin +set autoscale vfixmax +set xlabel "" +set xlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate +set x2label "" +set x2label offset character 0, 0, 0 font "" textcolor lt -1 norotate +set xrange [ * : * ] noreverse nowriteback # (currently [-0.150000:3.15000] ) +set autoscale xfixmin +set autoscale xfixmax +set x2range [ * : * ] noreverse nowriteback # (currently [0.00000:3.00000] ) +set autoscale x2fixmin +set autoscale x2fixmax +set ylabel "" +set ylabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set y2label "" +set y2label offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set yrange [ 0.00000 : 1.90000e+06 ] noreverse nowriteback # (currently [:] ) +set autoscale yfixmin +set autoscale yfixmax +set y2range [ * : * ] noreverse nowriteback # (currently [0.00000:1.90000e+06] ) +set autoscale y2fixmin +set autoscale y2fixmax +set zlabel "" +set zlabel offset character 0, 0, 0 font "" textcolor lt -1 norotate +set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] ) +set autoscale zfixmin +set autoscale zfixmax +set cblabel "" +set cblabel offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270 +set cbrange [ * : * ] noreverse nowriteback # (currently [8.98847e+307:-8.98847e+307] ) +set autoscale cbfixmin +set autoscale cbfixmax +set zero 1e-08 +set lmargin -1 +set bmargin -1 +set rmargin -1 +set tmargin -1 +set pm3d explicit at s +set pm3d scansautomatic +set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean +set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB +set palette rgbformulae 7, 5, 15 +set colorbox default +set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault +set loadpath +set fontpath +set fit noerrorvariables +GNUTERM = "aqua" +plot 'bench_results.txt' using 2:xticlabel(1) w lp lw 2, '' using 3:xticlabel(1) w lp lw 2, '' using 4:xticlabel(1) w lp lw 2, '' using 5:xticlabel(1) w lp lw 2, '' using 6:xticlabel(1) w lp lw 2, '' using 7:xticlabel(1) w lp lw 2, '' using 8:xticlabel(1) w lp lw 2, '' using 9:xticlabel(1) w lp lw 2 +# EOF diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.sh b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.sh new file mode 100755 index 000000000..d870a0cb0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# for a given node version run: +# for i in {0..9}; do node benchmark.js >> bench_0.6.2.log; done; + +PATTERNS=('nodeuuid.v1()' "nodeuuid.v1('binary'," 'nodeuuid.v4()' "nodeuuid.v4('binary'," "uuid()" "uuid('binary')" 'uuidjs.create(1)' 'uuidjs.create(4)' '140byte') +FILES=(node_uuid_v1_string node_uuid_v1_buf node_uuid_v4_string node_uuid_v4_buf libuuid_v4_string libuuid_v4_binary uuidjs_v1_string uuidjs_v4_string 140byte_es) +INDICES=(2 3 2 3 2 2 2 2 2) +VERSIONS=$( ls bench_*.log | sed -e 's/^bench_\([0-9\.]*\)\.log/\1/' | tr "\\n" " " ) +TMPJOIN="tmp_join" +OUTPUT="bench_results.txt" + +for I in ${!FILES[*]}; do + F=${FILES[$I]} + P=${PATTERNS[$I]} + INDEX=${INDICES[$I]} + echo "version $F" > $F + for V in $VERSIONS; do + (VAL=$( grep "$P" bench_$V.log | LC_ALL=en_US awk '{ sum += $'$INDEX' } END { print sum/NR }' ); echo $V $VAL) >> $F + done + if [ $I == 0 ]; then + cat $F > $TMPJOIN + else + join $TMPJOIN $F > $OUTPUT + cp $OUTPUT $TMPJOIN + fi + rm $F +done + +rm $TMPJOIN + +gnuplot bench.gnu +convert -density 200 -resize 800x560 -flatten bench.eps bench.png +rm bench.eps diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c new file mode 100644 index 000000000..dbfc75f6d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c @@ -0,0 +1,34 @@ +/* +Test performance of native C UUID generation + +To Compile: cc -luuid benchmark-native.c -o benchmark-native +*/ + +#include +#include +#include +#include + +int main() { + uuid_t myid; + char buf[36+1]; + int i; + struct timeval t; + double start, finish; + + gettimeofday(&t, NULL); + start = t.tv_sec + t.tv_usec/1e6; + + int n = 2e5; + for (i = 0; i < n; i++) { + uuid_generate(myid); + uuid_unparse(myid, buf); + } + + gettimeofday(&t, NULL); + finish = t.tv_sec + t.tv_usec/1e6; + double dur = finish - start; + + printf("%d uuids/sec", (int)(n/dur)); + return 0; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js new file mode 100644 index 000000000..40e6efbe7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js @@ -0,0 +1,84 @@ +try { + var nodeuuid = require('../uuid'); +} catch (e) { + console.error('node-uuid require failed - skipping tests'); +} + +try { + var uuid = require('uuid'); +} catch (e) { + console.error('uuid require failed - skipping tests'); +} + +try { + var uuidjs = require('uuid-js'); +} catch (e) { + console.error('uuid-js require failed - skipping tests'); +} + +var N = 5e5; + +function rate(msg, t) { + console.log(msg + ': ' + + (N / (Date.now() - t) * 1e3 | 0) + + ' uuids/second'); +} + +console.log('# v4'); + +// node-uuid - string form +if (nodeuuid) { + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4(); + rate('nodeuuid.v4() - using node.js crypto RNG', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4({rng: nodeuuid.mathRNG}); + rate('nodeuuid.v4() - using Math.random() RNG', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary'); + rate('nodeuuid.v4(\'binary\')', t); + + var buffer = new nodeuuid.BufferClass(16); + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary', buffer); + rate('nodeuuid.v4(\'binary\', buffer)', t); +} + +// libuuid - string form +if (uuid) { + for (var i = 0, t = Date.now(); i < N; i++) uuid(); + rate('uuid()', t); + + for (var i = 0, t = Date.now(); i < N; i++) uuid('binary'); + rate('uuid(\'binary\')', t); +} + +// uuid-js - string form +if (uuidjs) { + for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(4); + rate('uuidjs.create(4)', t); +} + +// 140byte.es +for (var i = 0, t = Date.now(); i < N; i++) 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(s,r){r=Math.random()*16|0;return (s=='x'?r:r&0x3|0x8).toString(16)}); +rate('140byte.es_v4', t); + +console.log(''); +console.log('# v1'); + +// node-uuid - v1 string form +if (nodeuuid) { + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1(); + rate('nodeuuid.v1()', t); + + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary'); + rate('nodeuuid.v1(\'binary\')', t); + + var buffer = new nodeuuid.BufferClass(16); + for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary', buffer); + rate('nodeuuid.v1(\'binary\', buffer)', t); +} + +// uuid-js - v1 string form +if (uuidjs) { + for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(1); + rate('uuidjs.create(1)', t); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/component.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/component.json new file mode 100644 index 000000000..ace213481 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/component.json @@ -0,0 +1,18 @@ +{ + "name": "node-uuid", + "repo": "broofa/node-uuid", + "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.", + "version": "1.4.0", + "author": "Robert Kieffer ", + "contributors": [ + {"name": "Christoph Tavan ", "github": "https://github.com/ctavan"} + ], + "keywords": ["uuid", "guid", "rfc4122"], + "dependencies": {}, + "development": {}, + "main": "uuid.js", + "scripts": [ + "uuid.js" + ], + "license": "MIT" +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/package.json new file mode 100644 index 000000000..0b2cc8ab4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/package.json @@ -0,0 +1,38 @@ +{ + "name": "node-uuid", + "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.", + "url": "http://github.com/broofa/node-uuid", + "keywords": [ + "uuid", + "guid", + "rfc4122" + ], + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Christoph Tavan", + "email": "dev@tavan.de" + } + ], + "lib": ".", + "main": "./uuid.js", + "repository": { + "type": "git", + "url": "https://github.com/broofa/node-uuid.git" + }, + "version": "1.4.1", + "readme": "# node-uuid\n\nSimple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.\n\nFeatures:\n\n* Generate RFC4122 version 1 or version 4 UUIDs\n* Runs in node.js and all browsers.\n* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').\n* Cryptographically strong random # generation on supporting platforms\n* 1.1K minified and gzip'ed (Want something smaller? Check this [crazy shit](https://gist.github.com/982883) out! )\n* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)\n\n## Getting Started\n\nInstall it in your browser:\n\n```html\n\n```\n\nOr in node.js:\n\n```\nnpm install node-uuid\n```\n\n```javascript\nvar uuid = require('node-uuid');\n```\n\nThen create some ids ...\n\n```javascript\n// Generate a v1 (time-based) id\nuuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n\n// Generate a v4 (random) id\nuuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'\n```\n\n## API\n\n### uuid.v1([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v1 (timestamp-based) UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID. See note 1.\n * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence. Default: An internally maintained clockseq is used.\n * `msecs` - (Number | Date) Time in milliseconds since unix Epoch. Default: The current time is used.\n * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nNotes:\n\n1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v1({\n node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],\n clockseq: 0x1234,\n msecs: new Date('2011-11-01').getTime(),\n nsecs: 5678\n}); // -> \"710b962e-041c-11e1-9234-0123456789ab\"\n```\n\nExample: In-place generation of two binary IDs\n\n```javascript\n// Generate two ids in an array\nvar arr = new Array(32); // -> []\nuuid.v1(null, arr, 0); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\nuuid.v1(null, arr, 16); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\n\n// Optionally use uuid.unparse() to get stringify the ids\nuuid.unparse(buffer); // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'\nuuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'\n```\n\n### uuid.v4([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v4 UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values\n * `rng` - (Function) Random # generator to use. Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v4({\n random: [\n 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,\n 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36\n ]\n});\n// -> \"109156be-c4fb-41ea-b1b4-efe1671c5836\"\n```\n\nExample: Generate two IDs in a single buffer\n\n```javascript\nvar buffer = new Array(32); // (or 'new Buffer' in node.js)\nuuid.v4(null, buffer, 0);\nuuid.v4(null, buffer, 16);\n```\n\n### uuid.parse(id[, buffer[, offset]])\n### uuid.unparse(buffer[, offset])\n\nParse and unparse UUIDs\n\n * `id` - (String) UUID(-like) string\n * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used\n * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0\n\nExample parsing and unparsing a UUID string\n\n```javascript\nvar bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> \nvar string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'\n```\n\n### uuid.noConflict()\n\n(Browsers only) Set `uuid` property back to it's previous value.\n\nReturns the node-uuid object.\n\nExample:\n\n```javascript\nvar myUuid = uuid.noConflict();\nmyUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n```\n\n## Deprecated APIs\n\nSupport for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.\n\n### uuid([format [, buffer [, offset]]])\n\nuuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).\n\n### uuid.BufferClass\n\nThe class of container created when generating binary uuid data if no buffer argument is specified. This is expected to go away, with no replacement API.\n\n## Testing\n\nIn node.js\n\n```\n> cd test\n> node test.js\n```\n\nIn Browser\n\n```\nopen test/test.html\n```\n\n### Benchmarking\n\nRequires node.js\n\n```\nnpm install uuid uuid-js\nnode benchmark/benchmark.js\n```\n\nFor a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)\n\nFor browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).\n\n## Release notes\n\n### 1.4.0\n\n* Improved module context detection\n* Removed public RNG functions\n\n### 1.3.2\n\n* Improve tests and handling of v1() options (Issue #24)\n* Expose RNG option to allow for perf testing with different generators\n\n### 1.3.0\n\n* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!\n* Support for node.js crypto API\n* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/broofa/node-uuid/issues" + }, + "_id": "node-uuid@1.4.1", + "dist": { + "shasum": "0a984adf144e58c48c2f4aaf7536e84365196e9d" + }, + "_from": "node-uuid@~1.4.0", + "_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/compare_v1.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/compare_v1.js new file mode 100644 index 000000000..05af82215 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/compare_v1.js @@ -0,0 +1,63 @@ +var assert = require('assert'), + nodeuuid = require('../uuid'), + uuidjs = require('uuid-js'), + libuuid = require('uuid').generate, + util = require('util'), + exec = require('child_process').exec, + os = require('os'); + +// On Mac Os X / macports there's only the ossp-uuid package that provides uuid +// On Linux there's uuid-runtime which provides uuidgen +var uuidCmd = os.type() === 'Darwin' ? 'uuid -1' : 'uuidgen -t'; + +function compare(ids) { + console.log(ids); + for (var i = 0; i < ids.length; i++) { + var id = ids[i].split('-'); + id = [id[2], id[1], id[0]].join(''); + ids[i] = id; + } + var sorted = ([].concat(ids)).sort(); + + if (sorted.toString() !== ids.toString()) { + console.log('Warning: sorted !== ids'); + } else { + console.log('everything in order!'); + } +} + +// Test time order of v1 uuids +var ids = []; +while (ids.length < 10e3) ids.push(nodeuuid.v1()); + +var max = 10; +console.log('node-uuid:'); +ids = []; +for (var i = 0; i < max; i++) ids.push(nodeuuid.v1()); +compare(ids); + +console.log(''); +console.log('uuidjs:'); +ids = []; +for (var i = 0; i < max; i++) ids.push(uuidjs.create(1).toString()); +compare(ids); + +console.log(''); +console.log('libuuid:'); +ids = []; +var count = 0; +var last = function() { + compare(ids); +} +var cb = function(err, stdout, stderr) { + ids.push(stdout.substring(0, stdout.length-1)); + count++; + if (count < max) { + return next(); + } + last(); +}; +var next = function() { + exec(uuidCmd, cb); +}; +next(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.html b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.html new file mode 100644 index 000000000..d80326ec5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.html @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js new file mode 100644 index 000000000..246922561 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js @@ -0,0 +1,228 @@ +if (!this.uuid) { + // node.js + uuid = require('../uuid'); +} + +// +// x-platform log/assert shims +// + +function _log(msg, type) { + type = type || 'log'; + + if (typeof(document) != 'undefined') { + document.write('
    ' + msg.replace(/\n/g, '
    ') + '
    '); + } + if (typeof(console) != 'undefined') { + var color = { + log: '\033[39m', + warn: '\033[33m', + error: '\033[31m' + }; + console[type](color[type] + msg + color.log); + } +} + +function log(msg) {_log(msg, 'log');} +function warn(msg) {_log(msg, 'warn');} +function error(msg) {_log(msg, 'error');} + +function assert(res, msg) { + if (!res) { + error('FAIL: ' + msg); + } else { + log('Pass: ' + msg); + } +} + +// +// Unit tests +// + +// Verify ordering of v1 ids created with explicit times +var TIME = 1321644961388; // 2011-11-18 11:36:01.388-08:00 + +function compare(name, ids) { + ids = ids.map(function(id) { + return id.split('-').reverse().join('-'); + }).sort(); + var sorted = ([].concat(ids)).sort(); + + assert(sorted.toString() == ids.toString(), name + ' have expected order'); +} + +// Verify ordering of v1 ids created using default behavior +compare('uuids with current time', [ + uuid.v1(), + uuid.v1(), + uuid.v1(), + uuid.v1(), + uuid.v1() +]); + +// Verify ordering of v1 ids created with explicit times +compare('uuids with time option', [ + uuid.v1({msecs: TIME - 10*3600*1000}), + uuid.v1({msecs: TIME - 1}), + uuid.v1({msecs: TIME}), + uuid.v1({msecs: TIME + 1}), + uuid.v1({msecs: TIME + 28*24*3600*1000}) +]); + +assert( + uuid.v1({msecs: TIME}) != uuid.v1({msecs: TIME}), + 'IDs created at same msec are different' +); + +// Verify throw if too many ids created +var thrown = false; +try { + uuid.v1({msecs: TIME, nsecs: 10000}); +} catch (e) { + thrown = true; +} +assert(thrown, 'Exception thrown when > 10K ids created in 1 ms'); + +// Verify clock regression bumps clockseq +var uidt = uuid.v1({msecs: TIME}); +var uidtb = uuid.v1({msecs: TIME - 1}); +assert( + parseInt(uidtb.split('-')[3], 16) - parseInt(uidt.split('-')[3], 16) === 1, + 'Clock regression by msec increments the clockseq' +); + +// Verify clock regression bumps clockseq +var uidtn = uuid.v1({msecs: TIME, nsecs: 10}); +var uidtnb = uuid.v1({msecs: TIME, nsecs: 9}); +assert( + parseInt(uidtnb.split('-')[3], 16) - parseInt(uidtn.split('-')[3], 16) === 1, + 'Clock regression by nsec increments the clockseq' +); + +// Verify explicit options produce expected id +var id = uuid.v1({ + msecs: 1321651533573, + nsecs: 5432, + clockseq: 0x385c, + node: [ 0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10 ] +}); +assert(id == 'd9428888-122b-11e1-b85c-61cd3cbb3210', 'Explicit options produce expected id'); + +// Verify adjacent ids across a msec boundary are 1 time unit apart +var u0 = uuid.v1({msecs: TIME, nsecs: 9999}); +var u1 = uuid.v1({msecs: TIME + 1, nsecs: 0}); + +var before = u0.split('-')[0], after = u1.split('-')[0]; +var dt = parseInt(after, 16) - parseInt(before, 16); +assert(dt === 1, 'Ids spanning 1ms boundary are 100ns apart'); + +// +// Test parse/unparse +// + +id = '00112233445566778899aabbccddeeff'; +assert(uuid.unparse(uuid.parse(id.substr(0,10))) == + '00112233-4400-0000-0000-000000000000', 'Short parse'); +assert(uuid.unparse(uuid.parse('(this is the uuid -> ' + id + id)) == + '00112233-4455-6677-8899-aabbccddeeff', 'Dirty parse'); + +// +// Perf tests +// + +var generators = { + v1: uuid.v1, + v4: uuid.v4 +}; + +var UUID_FORMAT = { + v1: /[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i, + v4: /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i +}; + +var N = 1e4; + +// Get %'age an actual value differs from the ideal value +function divergence(actual, ideal) { + return Math.round(100*100*(actual - ideal)/ideal)/100; +} + +function rate(msg, t) { + log(msg + ': ' + (N / (Date.now() - t) * 1e3 | 0) + ' uuids\/second'); +} + +for (var version in generators) { + var counts = {}, max = 0; + var generator = generators[version]; + var format = UUID_FORMAT[version]; + + log('\nSanity check ' + N + ' ' + version + ' uuids'); + for (var i = 0, ok = 0; i < N; i++) { + id = generator(); + if (!format.test(id)) { + throw Error(id + ' is not a valid UUID string'); + } + + if (id != uuid.unparse(uuid.parse(id))) { + assert(fail, id + ' is not a valid id'); + } + + // Count digits for our randomness check + if (version == 'v4') { + var digits = id.replace(/-/g, '').split(''); + for (var j = digits.length-1; j >= 0; j--) { + var c = digits[j]; + max = Math.max(max, counts[c] = (counts[c] || 0) + 1); + } + } + } + + // Check randomness for v4 UUIDs + if (version == 'v4') { + // Limit that we get worried about randomness. (Purely empirical choice, this!) + var limit = 2*100*Math.sqrt(1/N); + + log('\nChecking v4 randomness. Distribution of Hex Digits (% deviation from ideal)'); + + for (var i = 0; i < 16; i++) { + var c = i.toString(16); + var bar = '', n = counts[c], p = Math.round(n/max*100|0); + + // 1-3,5-8, and D-F: 1:16 odds over 30 digits + var ideal = N*30/16; + if (i == 4) { + // 4: 1:1 odds on 1 digit, plus 1:16 odds on 30 digits + ideal = N*(1 + 30/16); + } else if (i >= 8 && i <= 11) { + // 8-B: 1:4 odds on 1 digit, plus 1:16 odds on 30 digits + ideal = N*(1/4 + 30/16); + } else { + // Otherwise: 1:16 odds on 30 digits + ideal = N*30/16; + } + var d = divergence(n, ideal); + + // Draw bar using UTF squares (just for grins) + var s = n/max*50 | 0; + while (s--) bar += '='; + + assert(Math.abs(d) < limit, c + ' |' + bar + '| ' + counts[c] + ' (' + d + '% < ' + limit + '%)'); + } + } +} + +// Perf tests +for (var version in generators) { + log('\nPerformance testing ' + version + ' UUIDs'); + var generator = generators[version]; + var buf = new uuid.BufferClass(16); + + for (var i = 0, t = Date.now(); i < N; i++) generator(); + rate('uuid.' + version + '()', t); + + for (var i = 0, t = Date.now(); i < N; i++) generator('binary'); + rate('uuid.' + version + '(\'binary\')', t); + + for (var i = 0, t = Date.now(); i < N; i++) generator('binary', buf); + rate('uuid.' + version + '(\'binary\', buffer)', t); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js new file mode 100644 index 000000000..2fac6dc4b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js @@ -0,0 +1,245 @@ +// uuid.js +// +// Copyright (c) 2010-2012 Robert Kieffer +// MIT License - http://opensource.org/licenses/mit-license.php + +(function() { + var _global = this; + + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + var _rng; + + // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html + // + // Moderately fast, high quality + if (typeof(require) == 'function') { + try { + var _rb = require('crypto').randomBytes; + _rng = _rb && function() {return _rb(16);}; + } catch(e) {} + } + + if (!_rng && _global.crypto && crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + } + + // Buffer class to use + var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq != null ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs != null ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; + + if (typeof define === 'function' && define.amd) { + // Publish as AMD module + define(function() {return uuid;}); + } else if (typeof(module) != 'undefined' && module.exports) { + // Publish as node.js module + module.exports = uuid; + } else { + // Publish as global (in browsers) + var _previousRoot = _global.uuid; + + // **`noConflict()` - (browser only) to reset global 'uuid' var** + uuid.noConflict = function() { + _global.uuid = _previousRoot; + return uuid; + }; + + _global.uuid = uuid; + } +}).call(this); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE new file mode 100644 index 000000000..a4a9aee0c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md new file mode 100644 index 000000000..34c4a85d2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md @@ -0,0 +1,4 @@ +oauth-sign +========== + +OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js new file mode 100644 index 000000000..e35bfa670 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js @@ -0,0 +1,43 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function rfc3986 (str) { + return encodeURIComponent(str) + .replace(/!/g,'%21') + .replace(/\*/g,'%2A') + .replace(/\(/g,'%28') + .replace(/\)/g,'%29') + .replace(/'/g,'%27') + ; +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) { + // adapted from https://dev.twitter.com/docs/auth/oauth and + // https://dev.twitter.com/docs/auth/creating-signature + + var querystring = Object.keys(params).sort().map(function(key){ + // big WTF here with the escape + encoding but it's what twitter wants + return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key])) + }).join('%26') + + var base = [ + httpMethod ? httpMethod.toUpperCase() : 'GET', + rfc3986(base_uri), + querystring + ].join('&') + + var key = [ + consumer_secret, + token_secret || '' + ].map(rfc3986).join('&') + + return sha1(key, base) +} + +exports.hmacsign = hmacsign +exports.rfc3986 = rfc3986 diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json new file mode 100644 index 000000000..f7d367144 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json @@ -0,0 +1,34 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "oauth-sign", + "description": "OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/oauth-sign" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "scripts": { + "test": "node test.js" + }, + "readme": "oauth-sign\n==========\n\nOAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. \n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mikeal/oauth-sign/issues" + }, + "_id": "oauth-sign@0.3.0", + "dist": { + "shasum": "3d6859f0cd030db4bf7ff3ed797fb79165cec2c6" + }, + "_from": "oauth-sign@~0.3.0", + "_resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js new file mode 100644 index 000000000..46955ff69 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js @@ -0,0 +1,49 @@ +var hmacsign = require('./index').hmacsign + , assert = require('assert') + , qs = require('querystring') + ; + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.gitmodules b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.gitmodules new file mode 100644 index 000000000..49e31dac7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.npmignore new file mode 100644 index 000000000..e85ce2afa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/.npmignore @@ -0,0 +1,7 @@ +test +.travis.yml +benchmark.js +component.json +examples.js +History.md +Makefile diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/Readme.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/Readme.md new file mode 100644 index 000000000..27e54a4af --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/index.js new file mode 100644 index 000000000..590491e31 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/index.js @@ -0,0 +1,387 @@ +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Object#hasOwnProperty ref + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Array#indexOf shim. + */ + +var indexOf = typeof Array.prototype.indexOf === 'function' + ? function(arr, el) { return arr.indexOf(el); } + : function(arr, el) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === el) return i; + } + return -1; + }; + +/** + * Array.isArray shim. + */ + +var isArray = Array.isArray || function(arr) { + return toString.call(arr) == '[object Array]'; +}; + +/** + * Object.keys shim. + */ + +var objectKeys = Object.keys || function(obj) { + var ret = []; + for (var key in obj) ret.push(key); + return ret; +}; + +/** + * Array#forEach shim. + */ + +var forEach = typeof Array.prototype.forEach === 'function' + ? function(arr, fn) { return arr.forEach(fn); } + : function(arr, fn) { + for (var i = 0; i < arr.length; i++) fn(arr[i]); + }; + +/** + * Array#reduce shim. + */ + +var reduce = function(arr, fn, initial) { + if (typeof arr.reduce === 'function') return arr.reduce(fn, initial); + var res = initial; + for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]); + return res; +}; + +/** + * Create a nullary object if possible + */ + +function createObject() { + return Object.create + ? Object.create(null) + : {}; +} + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = createObject(); + var t = createObject(); + for (var i in parent[key]) { + if (hasOwnProperty.call(parent[key], i)) { + t[i] = parent[key][i]; + } + } + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[objectKeys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~indexOf(part, ']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~indexOf(key, ']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && isArray(parent.base)) { + var t = createObject(); + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Compact sparse arrays. + */ + +function compact(obj) { + if ('object' != typeof obj) return obj; + + if (isArray(obj)) { + var ret = []; + + for (var i in obj) { + if (hasOwnProperty.call(obj, i)) { + ret.push(obj[i]); + } + } + + return ret; + } + + for (var key in obj) { + obj[key] = compact(obj[key]); + } + + return obj; +} + +/** + * Restore Object.prototype. + * see pull-request #58 + */ + +function restoreProto(obj) { + if (!Object.create) return obj; + if (isArray(obj)) return obj; + if (obj && 'object' != typeof obj) return obj; + + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + obj[key] = restoreProto(obj[key]); + } + } + + obj.__proto__ = Object.prototype; + return obj; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + + forEach(objectKeys(obj), function(name){ + merge(ret, name, obj[name]); + }); + + return compact(ret.base); +} + +/** + * Parse the given str. + */ + +function parseString(str){ + var ret = reduce(String(str).split('&'), function(ret, pair){ + var eql = indexOf(pair, '=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(indexOf(val, '=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: createObject() }).base; + + return restoreProto(compact(ret)); +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = objectKeys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/package.json new file mode 100644 index 000000000..f60326ca4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/qs/package.json @@ -0,0 +1,41 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.6.5", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "scripts": { + "test": "make test" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/node-querystring/issues" + }, + "_id": "qs@0.6.5", + "dist": { + "shasum": "71da97e9a2b605fbc4c51a28b47106c8732e3c41" + }, + "_from": "qs@~0.6.0", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE new file mode 100644 index 000000000..a4a9aee0c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md new file mode 100644 index 000000000..bb533d56b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md @@ -0,0 +1,4 @@ +tunnel-agent +============ + +HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js new file mode 100644 index 000000000..3f7bbb909 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js @@ -0,0 +1,227 @@ +'use strict' + +var net = require('net') + , tls = require('tls') + , http = require('http') + , https = require('https') + , events = require('events') + , assert = require('assert') + , util = require('util') + ; + +exports.httpOverHttp = httpOverHttp +exports.httpsOverHttp = httpsOverHttp +exports.httpOverHttps = httpOverHttps +exports.httpsOverHttps = httpsOverHttps + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + return agent +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + agent.createSocket = createSecureSocket + return agent +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + return agent +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + agent.createSocket = createSecureSocket + return agent +} + + +function TunnelingAgent(options) { + var self = this + self.options = options || {} + self.proxyOptions = self.options.proxy || {} + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets + self.requests = [] + self.sockets = [] + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i] + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1) + pending.request.onSocket(socket) + return + } + } + socket.destroy() + self.removeSocket(socket) + }) +} +util.inherits(TunnelingAgent, events.EventEmitter) + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}) + return + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree) + socket.on('close', onCloseOrRemove) + socket.on('agentRemove', onCloseOrRemove) + req.onSocket(socket) + + function onFree() { + self.emit('free', socket, host, port) + } + + function onCloseOrRemove(err) { + self.removeSocket() + socket.removeListener('free', onFree) + socket.removeListener('close', onCloseOrRemove) + socket.removeListener('agentRemove', onCloseOrRemove) + } + }) +} + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this + var placeholder = {} + self.sockets.push(placeholder) + + var connectOptions = mergeOptions({}, self.proxyOptions, + { method: 'CONNECT' + , path: options.host + ':' + options.port + , agent: false + } + ) + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {} + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64') + } + + debug('making CONNECT request') + var connectReq = self.request(connectOptions) + connectReq.useChunkedEncodingByDefault = false // for v0.6 + connectReq.once('response', onResponse) // for v0.6 + connectReq.once('upgrade', onUpgrade) // for v0.6 + connectReq.once('connect', onConnect) // for v0.7 or later + connectReq.once('error', onError) + connectReq.end() + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head) + }) + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners() + socket.removeAllListeners() + + if (res.statusCode === 200) { + assert.equal(head.length, 0) + debug('tunneling connection has established') + self.sockets[self.sockets.indexOf(placeholder)] = socket + cb(socket) + } else { + debug('tunneling socket could not be established, statusCode=%d', res.statusCode) + var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } + } + + function onError(cause) { + connectReq.removeAllListeners() + + debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack) + var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } +} + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) return + + this.sockets.splice(pos, 1) + + var pending = this.requests.shift() + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket) + }) + } +} + +function createSecureSocket(options, cb) { + var self = this + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, + { servername: options.host + , socket: socket + } + )) + cb(secureSocket) + }) +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i] + if (typeof overrides === 'object') { + var keys = Object.keys(overrides) + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j] + if (overrides[k] !== undefined) { + target[k] = overrides[k] + } + } + } + } + return target +} + + +var debug +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments) + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0] + } else { + args.unshift('TUNNEL:') + } + console.error.apply(console, args) + } +} else { + debug = function() {} +} +exports.debug = debug // for test diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json new file mode 100644 index 000000000..da9806482 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "tunnel-agent", + "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/tunnel-agent" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "tunnel-agent\n============\n\nHTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mikeal/tunnel-agent/issues" + }, + "_id": "tunnel-agent@0.3.0", + "dist": { + "shasum": "5e6da0a72a4352d14aaa9593d85ea7d577a55aae" + }, + "_from": "tunnel-agent@~0.3.0", + "_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/package.json new file mode 100755 index 000000000..3ce13444d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/package.json @@ -0,0 +1,51 @@ +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.27.0", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.8.0" + ], + "main": "index.js", + "dependencies": { + "qs": "~0.6.0", + "json-stringify-safe": "~5.0.0", + "forever-agent": "~0.5.0", + "tunnel-agent": "~0.3.0", + "http-signature": "~0.10.0", + "hawk": "~1.0.0", + "aws-sign": "~0.3.0", + "oauth-sign": "~0.3.0", + "cookie-jar": "~0.3.0", + "node-uuid": "~1.4.0", + "mime": "~1.2.9", + "form-data": "~0.1.0" + }, + "scripts": { + "test": "node tests/run.js" + }, + "readme": "# Request -- Simplified HTTP client\n\n[![NPM](https://nodei.co/npm/request.png)](https://nodei.co/npm/request/)\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n }\n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## HTTP Authentication\n\n```javascript\nrequest.get('http://some.server.com/').auth('username', 'password', false);\n// or\nrequest.get('http://some.server.com/', {\n 'auth': {\n 'user': 'username',\n 'pass': 'password',\n 'sendImmediately': false\n }\n});\n```\n\nIf passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`.\n\n`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).\n\nDigest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Ideally, you would take the body in the response\n // and construct a URL that a user clicks on (like a sign in button).\n // The verifier is only available in the response after a user has\n // verified with twitter that they are authorizing your app.\n var access_token = qs.parse(body)\n , oauth =\n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: access_token.oauth_verifier\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth =\n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params =\n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `true` if you want cookies to be remembered for future use, or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.\n* `localAddress` - Local interface to bind for network connections.\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second is an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options)\n\nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.patch\n\nSame as request() but defaults to `method: \"PATCH\"`.\n\n```javascript\nrequest.patch(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart:\n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ]\n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are disabled by default (else, they would be used in subsequent requests). To enable cookies set jar to true (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: true})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "readmeFilename": "README.md", + "_id": "request@2.27.0", + "dist": { + "shasum": "221244253e49fd86949f5986c56954526fca9f6c" + }, + "_from": "request@>=2.12.0", + "_resolved": "https://registry.npmjs.org/request/-/request-2.27.0.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/request.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/request.js new file mode 100644 index 000000000..0311f743d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/request.js @@ -0,0 +1,1235 @@ +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('qs') + , querystring = require('querystring') + , crypto = require('crypto') + + , oauth = require('oauth-sign') + , hawk = require('hawk') + , aws = require('aws-sign') + , httpSignature = require('http-signature') + , uuid = require('node-uuid') + , mime = require('mime') + , tunnel = require('tunnel-agent') + , _safeStringify = require('json-stringify-safe') + + , ForeverAgent = require('forever-agent') + , FormData = require('form-data') + + , Cookie = require('cookie-jar') + , CookieJar = Cookie.Jar + , cookieJar = new CookieJar + + , copy = require('./lib/copy') + , debug = require('./lib/debug') + , getSafe = require('./lib/getSafe') + ; + +function safeStringify (obj) { + var ret + try { ret = JSON.stringify(obj) } + catch (e) { ret = _safeStringify(obj) } + return ret +} + +var globalPool = {} +var isUrl = /^https?:/i + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + + + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function (host, port, cb) { + var s = tls.connect(port, host, this.options, function () { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +function md5 (str) { + return crypto.createHash('md5').update(str).digest('hex') +} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + var reserved = Object.keys(Request.prototype) + for (var i in options) { + if (reserved.indexOf(i) === -1) { + this[i] = options[i] + } else { + if (typeof options[i] === 'function') { + delete options[i] + } + } + } + + if (options.method) { + this.explicitMethod = true + } + + this.init(options) +} +util.inherits(Request, stream.Stream) +Request.prototype.init = function (options) { + // init() contains all the code to setup the request object. + // the actual outgoing request is not started until start() is called + // this function is called from both the constructor and on redirect. + var self = this + if (!options) options = {} + + if (!self.method) self.method = options.method || 'GET' + self.localAddress = options.localAddress + + debug(options) + if (!self.pool && self.pool !== false) self.pool = globalPool + self.dests = self.dests || [] + self.__isRequestRequest = true + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callbackCalled = true + self._callback.apply(self, arguments) + } + self.on('error', self.callback.bind()) + self.on('complete', self.callback.bind(self, null)) + } + + if (self.url && !self.uri) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + // this will throw if unhandled but is handleable when in a redirect + return self.emit('error', new Error("options.uri is a required argument")) + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + + if (self.strictSSL === false) { + self.rejectUnauthorized = false + } + + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth + , headers: { Host: self.uri.hostname + ':' + + (self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }} + , rejectUnauthorized: self.rejectUnauthorized + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } + } + + if (!self.uri.pathname) {self.uri.pathname = '/'} + + if (!self.uri.host) { + // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar + // Detect and reject it as soon as possible + var faultyUri = url.format(self.uri) + var message = 'Invalid URI "' + faultyUri + '"' + if (Object.keys(options).length === 0) { + // No option ? This can be the sign of a redirect + // As this is a case where the user cannot do anything (he didn't call request directly with this URL) + // he should be warned that it can be caused by a redirection (can save some hair) + message += '. This can be caused by a crappy redirection.' + } + self.emit('error', new Error(message)) + return // This error was fatal + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false + if (self.followRedirect || self.followAllRedirects) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + self.setHost = false + if (!self.hasHeader('host')) { + self.setHeader('host', self.uri.hostname) + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.setHeader('host', self.getHeader('host') + (':'+self.uri.port) ) + } + self.setHost = true + } + + self.jar(self._jar || options.jar) + + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy && !self.tunnel) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + self.clientErrorHandler = function (error) { + if (self._aborted) return + + if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } + self.start() + self.req.end() + return + } + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + self.emit('error', error) + } + + self._parserErrorHandler = function (error) { + if (this.res) { + if (this.res.request) { + this.res.request.emit('error', error) + } else { + this.res.emit('error', error) + } + } else { + this._httpMessage.emit('error', error) + } + } + + if (options.form) { + self.form(options.form) + } + + if (options.qs) self.qs(options.qs) + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + + // Auth must happen last in case signing is dependent on other headers + if (options.oauth) { + self.oauth(options.oauth) + } + + if (options.aws) { + self.aws(options.aws) + } + + if (options.hawk) { + self.hawk(options.hawk) + } + + if (options.httpSignature) { + self.httpSignature(options.httpSignature) + } + + if (options.auth) { + self.auth( + (options.auth.user==="") ? options.auth.user : (options.auth.user || options.auth.username ), + options.auth.pass || options.auth.password, + options.auth.sendImmediately) + } + + if (self.uri.auth && !self.hasHeader('authorization')) { + var authPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) }) + self.auth(authPieces[0], authPieces.slice(1).join(':'), true) + } + if (self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization') && !self.tunnel) { + self.setHeader('proxy-authorization', "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':'))) + } + + + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (options.json) { + self.json(options.json) + } else if (options.multipart) { + self.boundary = uuid() + self.multipart(options.multipart) + } + + if (self.body) { + var length = 0 + if (!Buffer.isBuffer(self.body)) { + if (Array.isArray(self.body)) { + for (var i = 0; i < self.body.length; i++) { + length += self.body[i].length + } + } else { + self.body = new Buffer(self.body) + length = self.body.length + } + } else { + length = self.body.length + } + if (length) { + if (!self.hasHeader('content-length')) self.setHeader('content-length', length) + } else { + throw new Error('Argument error, options.body.') + } + } + + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol + , defaultModules = {'http:':http, 'https:':https} + , httpModules = self.httpModules || {} + ; + self.httpModule = httpModules[protocol] || defaultModules[protocol] + + if (!self.httpModule) return this.emit('error', new Error("Invalid protocol")) + + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + + if (self.pool === false) { + self.agent = false + } else { + self.agent = self.agent || self.getAgent() + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.on('pipe', function (src) { + if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") + self.src = src + if (isReadStream(src)) { + if (!self.hasHeader('content-type')) self.setHeader('content-type', mime.lookup(src.path)) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.hasHeader(i)) { + self.setHeader(i, src.headers[i]) + } + } + } + if (self._json && !self.hasHeader('content-type')) + self.setHeader('content-type', 'application/json') + if (src.method && !self.explicitMethod) { + self.method = src.method + } + } + + // self.on('pipe', function () { + // console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + // }) + }) + + process.nextTick(function () { + if (self._aborted) return + + if (self._form) { + self.setHeaders(self._form.getHeaders()) + self._form.pipe(self) + } + if (self.body) { + if (Array.isArray(self.body)) { + self.body.forEach(function (part) { + self.write(part) + }) + } else { + self.write(self.body) + } + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + if (self.method !== 'GET' && typeof self.method !== 'undefined') { + self.setHeader('content-length', 0) + } + self.end() + } + self.ntick = true + }) +} + +// Must call this when following a redirect from https to http or vice versa +// Attempts to keep everything as identical as possible, but update the +// httpModule, Tunneling agent, and/or Forever Agent in use. +Request.prototype._updateProtocol = function () { + var self = this + var protocol = self.uri.protocol + + if (protocol === 'https:') { + // previously was doing http, now doing https + // if it's https, then we might need to tunnel now. + if (self.proxy) { + self.tunnel = true + var tunnelFn = self.proxy.protocol === 'http:' + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth } + , rejectUnauthorized: self.rejectUnauthorized + , ca: self.ca } + self.agent = tunnelFn(tunnelOptions) + return + } + + self.httpModule = https + switch (self.agentClass) { + case ForeverAgent: + self.agentClass = ForeverAgent.SSL + break + case http.Agent: + self.agentClass = https.Agent + break + default: + // nothing we can do. Just hope for the best. + return + } + + // if there's an agent, we need to get a new one. + if (self.agent) self.agent = self.getAgent() + + } else { + // previously was doing https, now doing http + // stop any tunneling. + if (self.tunnel) self.tunnel = false + self.httpModule = http + switch (self.agentClass) { + case ForeverAgent.SSL: + self.agentClass = ForeverAgent + break + case https.Agent: + self.agentClass = http.Agent + break + default: + // nothing we can do. just hope for the best + return + } + + // if there's an agent, then get a new one. + if (self.agent) { + self.agent = null + self.agent = self.getAgent() + } + } +} + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + if (typeof this.rejectUnauthorized !== 'undefined') options.rejectUnauthorized = this.rejectUnauthorized + + if (this.cert && this.key) { + options.key = this.key + options.cert = this.cert + } + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port + } + + // ca option is only relevant if proxy or destination are https + var proxy = this.proxy + if (typeof proxy === 'string') proxy = url.parse(proxy) + var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' + if (isHttps) { + if (options.ca) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (typeof options.rejectUnauthorized !== 'undefined') { + if (poolKey) poolKey += ':' + poolKey += options.rejectUnauthorized + } + + if (options.cert) + poolKey += options.cert.toString('ascii') + options.key.toString('ascii') + + if (options.ciphers) { + if (poolKey) poolKey += ':' + poolKey += options.ciphers + } + + if (options.secureOptions) { + if (poolKey) poolKey += ':' + poolKey += options.secureOptions + } + } + + if (this.pool === globalPool && !poolKey && Object.keys(options).length === 0 && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // we're using a stored agent. Make sure it's protocol-specific + poolKey = this.uri.protocol + poolKey + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) +} + +Request.prototype.start = function () { + // start() is called once we are ready to send the outgoing HTTP request. + // this is usually called on the first write(), end() or on nextTick() + var self = this + + if (self._aborted) return + + self._started = true + self.method = self.method || 'GET' + self.href = self.uri.href + + if (self.src && self.src.stat && self.src.stat.size && !self.hasHeader('content-length')) { + self.setHeader('content-length', self.src.stat.size) + } + if (self._aws) { + self.aws(self._aws, true) + } + + // We have a method named auth, which is completely different from the http.request + // auth option. If we don't remove it, we're gonna have a bad time. + var reqOptions = copy(self) + delete reqOptions.auth + + debug('make request', self.uri.href) + self.req = self.httpModule.request(reqOptions, self.onResponse.bind(self)) + + if (self.timeout && !self.timeoutTimer) { + self.timeoutTimer = setTimeout(function () { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + + // Set additional timeout on socket - in case if remote + // server freeze after sending headers + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function () { + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } + } + + self.req.on('error', self.clientErrorHandler) + self.req.on('drain', function() { + self.emit('drain') + }) + self.on('end', function() { + if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler) + }) + self.emit('request', self.req) +} +Request.prototype.onResponse = function (response) { + var self = this + debug('onResponse', self.uri.href, response.statusCode, response.headers) + response.on('end', function() { + debug('response end', self.uri.href, response.statusCode, response.headers) + }); + + if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) { + response.connection.once('error', self._parserErrorHandler) + } + if (self._aborted) { + debug('aborted', self.uri.href) + response.resume() + return + } + if (self._paused) response.pause() + else response.resume() + + self.response = response + response.request = self + response.toJSON = toJSON + + // XXX This is different on 0.10, because SSL is strict by default + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + debug('strict ssl error', self.uri.href) + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (self.setHost && self.hasHeader('host')) delete self.headers[self.hasHeader('host')] + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + + var addCookie = function (cookie) { + if (self._jar){ + if(self._jar.add){ + self._jar.add(new Cookie(cookie)) + } + else cookieJar.add(new Cookie(cookie)) + } + + } + + if (hasHeader('set-cookie', response.headers) && (!self._disableCookies)) { + var headerName = hasHeader('set-cookie', response.headers) + if (Array.isArray(response.headers[headerName])) response.headers[headerName].forEach(addCookie) + else addCookie(response.headers[headerName]) + } + + var redirectTo = null + if (response.statusCode >= 300 && response.statusCode < 400 && hasHeader('location', response.headers)) { + var location = response.headers[hasHeader('location', response.headers)] + debug('redirect', location) + + if (self.followAllRedirects) { + redirectTo = location + } else if (self.followRedirect) { + switch (self.method) { + case 'PATCH': + case 'PUT': + case 'POST': + case 'DELETE': + // Do not follow redirects + break + default: + redirectTo = location + break + } + } + } else if (response.statusCode == 401 && self._hasAuth && !self._sentAuth) { + var authHeader = response.headers[hasHeader('www-authenticate', response.headers)] + var authVerb = authHeader && authHeader.split(' ')[0] + debug('reauth', authVerb) + + switch (authVerb) { + case 'Basic': + self.auth(self._user, self._pass, true) + redirectTo = self.uri + break + + case 'Digest': + // TODO: More complete implementation of RFC 2617. For reference: + // http://tools.ietf.org/html/rfc2617#section-3 + // https://github.com/bagder/curl/blob/master/lib/http_digest.c + + var matches = authHeader.match(/([a-z0-9_-]+)="([^"]+)"/gi) + var challenge = {} + + for (var i = 0; i < matches.length; i++) { + var eqPos = matches[i].indexOf('=') + var key = matches[i].substring(0, eqPos) + var quotedValue = matches[i].substring(eqPos + 1) + challenge[key] = quotedValue.substring(1, quotedValue.length - 1) + } + + var ha1 = md5(self._user + ':' + challenge.realm + ':' + self._pass) + var ha2 = md5(self.method + ':' + self.uri.path) + var digestResponse = md5(ha1 + ':' + challenge.nonce + ':1::auth:' + ha2) + var authValues = { + username: self._user, + realm: challenge.realm, + nonce: challenge.nonce, + uri: self.uri.path, + qop: challenge.qop, + response: digestResponse, + nc: 1, + cnonce: '' + } + + authHeader = [] + for (var k in authValues) { + authHeader.push(k + '="' + authValues[k] + '"') + } + authHeader = 'Digest ' + authHeader.join(', ') + self.setHeader('authorization', authHeader) + self._sentAuth = true + + redirectTo = self.uri + break + } + } + + if (redirectTo) { + debug('redirect to', redirectTo) + + // ignore any potential response body. it cannot possibly be useful + // to us at this point. + if (self._paused) response.resume() + + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href)) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(redirectTo)) { + redirectTo = url.resolve(self.uri.href, redirectTo) + } + + var uriPrev = self.uri + self.uri = url.parse(redirectTo) + + // handle the case where we change protocol from https to http or vice versa + if (self.uri.protocol !== uriPrev.protocol) { + self._updateProtocol() + } + + self.redirects.push( + { statusCode : response.statusCode + , redirectUri: redirectTo + } + ) + if (self.followAllRedirects && response.statusCode != 401) self.method = 'GET' + // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215 + delete self.src + delete self.req + delete self.agent + delete self._started + if (response.statusCode != 401) { + // Remove parameters from the previous response, unless this is the second request + // for a server that requires digest authentication. + delete self.body + delete self._form + if (self.headers) { + if (self.hasHeader('host')) delete self.headers[self.hasHeader('host')] + if (self.hasHeader('content-type')) delete self.headers[self.hasHeader('content-type')] + if (self.hasHeader('content-length')) delete self.headers[self.hasHeader('content-length')] + } + } + + self.emit('redirect'); + + self.init() + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ignoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.emit('response', response) + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + debug('end event', self.uri.href) + if (self._aborted) { + debug('aborted', self.uri.href) + return + } + + if (buffer.length && Buffer.isBuffer(buffer[0])) { + debug('has body', self.uri.href, bodyLen) + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + if (self.encoding === null) { + response.body = body + } else { + response.body = body.toString(self.encoding) + } + } else if (buffer.length) { + // The UTF8 BOM [0xEF,0xBB,0xBF] is converted to [0xFE,0xFF] in the JS UTC16/UCS2 representation. + // Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse(). + if (self.encoding === 'utf8' && buffer[0].length > 0 && buffer[0][0] === "\uFEFF") { + buffer[0] = buffer[0].substring(1) + } + response.body = buffer.join('') + } + + if (self._json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + debug('emitting complete', self.uri.href) + if(response.body == undefined && !self._json) { + response.body = ""; + } + self.emit('complete', response, response.body) + }) + } + //if no callback + else{ + self.on("end", function () { + if (self._aborted) { + debug('aborted', self.uri.href) + return + } + self.emit('complete', response); + }); + } + } + debug('finish init function', self.uri.href) +} + +Request.prototype.abort = function () { + this._aborted = true + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + +Request.prototype.pipeDest = function (dest) { + var response = this.response + // Called after the response is received + if (dest.headers && !dest.headersSent) { + if (hasHeader('content-type', response.headers)) { + var ctname = hasHeader('content-type', response.headers) + if (dest.setHeader) dest.setHeader(ctname, response.headers[ctname]) + else dest.headers[ctname] = response.headers[ctname] + } + + if (hasHeader('content-length', response.headers)) { + var clname = hasHeader('content-length', response.headers) + if (dest.setHeader) dest.setHeader(clname, response.headers[clname]) + else dest.headers[clname] = response.headers[clname] + } + } + if (dest.setHeader && !dest.headersSent) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (this.pipefilter) this.pipefilter(response, dest) +} + +// Composable API +Request.prototype.setHeader = function (name, value, clobber) { + if (clobber === undefined) clobber = true + if (clobber || !this.hasHeader(name)) this.headers[name] = value + else this.headers[this.hasHeader(name)] += ',' + value + return this +} +Request.prototype.setHeaders = function (headers) { + for (var i in headers) {this.setHeader(i, headers[i])} + return this +} +Request.prototype.hasHeader = function (header, headers) { + var headers = Object.keys(headers || this.headers) + , lheaders = headers.map(function (h) {return h.toLowerCase()}) + ; + header = header.toLowerCase() + for (var i=0;iOh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + , testPutMultipartPreambleCRLF : + { resp: server.createPostValidator( + '\r\n--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , preambleCRLF: true + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-defaults.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-defaults.js new file mode 100644 index 000000000..f6c402460 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-defaults.js @@ -0,0 +1,129 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/patch', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'PATCH') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).patch(s.url + '/patch', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/post-body', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) with body + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + }); + + s.on('/get_custom', function(req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers.x, 'y'); + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test custom request handler function + var defaultRequest = request.defaults({ + headers:{foo:"bar"} + , body: 'TESTING!' + }, function(uri, options, callback) { + var params = request.initParams(uri, options, callback); + options = params.options; + options.headers.x = 'y'; + + return request(params.uri, params.options, params.callback); + }); + + var msg = 'defaults test failed. head request should throw earlier'; + assert.throws(function() { + defaultRequest.head(s.url + '/get_custom', function(e, r, b) { + throw new Error(msg); + }); + counter+=1; + }, msg); + + defaultRequest.get(s.url + '/get_custom', function(e, r, b) { + if(e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed."); + s.close(); + }); +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-digest-auth.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-digest-auth.js new file mode 100644 index 000000000..5f2d6eb7d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-digest-auth.js @@ -0,0 +1,69 @@ +var assert = require('assert') + , http = require('http') + , request = require('../index') + ; + +// Test digest auth +// Using header values captured from interaction with Apache + +var numDigestRequests = 0; + +var digestServer = http.createServer(function (req, res) { + console.error('Digest auth server: ', req.method, req.url); + numDigestRequests++; + + var ok; + + if (req.headers.authorization) { + if (req.headers.authorization == 'Digest username="test", realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", uri="/test/", qop="auth", response="54753ce37c10cb20b09b769f0bed730e", nc="1", cnonce=""') { + ok = true; + } else { + // Bad auth header, don't send back WWW-Authenticate header + ok = false; + } + } else { + // No auth header, send back WWW-Authenticate header + ok = false; + res.setHeader('www-authenticate', 'Digest realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", algorithm=MD5, qop="auth"'); + } + + if (ok) { + console.log('request ok'); + res.end('ok'); + } else { + console.log('status=401'); + res.statusCode = 401; + res.end('401'); + } +}); + +digestServer.listen(6767); + +request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing', + 'sendImmediately': false + } +}, function(error, response, body) { + assert.equal(response.statusCode, 200); + assert.equal(numDigestRequests, 2); + + // If we don't set sendImmediately = false, request will send basic auth + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing' + } + }, function(error, response, body) { + assert.equal(response.statusCode, 401); + assert.equal(numDigestRequests, 3); + + console.log('All tests passed'); + digestServer.close(); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-emptyBody.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-emptyBody.js new file mode 100644 index 000000000..338c92e5e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-emptyBody.js @@ -0,0 +1,20 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp, body) { + assert.equal(resp.statusCode, 200) + assert.equal(body, "") + + var r2 = request({ url: 'http://localhost:8080', json: {} }, function (e, resp, body) { + assert.equal(resp.statusCode, 200) + assert.equal(body, undefined) + s.close() + }); + }) +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-errors.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-errors.js new file mode 100644 index 000000000..4df1302a0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../index') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all-303.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all-303.js new file mode 100644 index 000000000..956e386d1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all-303.js @@ -0,0 +1,30 @@ +var request = require('../index'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + console.error(req.method, req.url); + requests ++; + + if (req.method === 'POST') { + console.error('send 303'); + res.setHeader('location', req.url); + res.statusCode = 303; + res.end('try again, i guess\n'); + } else { + console.error('send 200') + res.end('ok: ' + requests); + } +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 2'); + assert.equal(requests, 2); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all.js new file mode 100644 index 000000000..f2e51ffa7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-follow-all.js @@ -0,0 +1,36 @@ +var request = require('../index'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + requests ++; + + // redirect everything 3 times, no matter what. + var c = req.headers.cookie; + + if (!c) c = 0; + else c = +c.split('=')[1] || 0; + + if (c > 3) { + res.end('ok: '+requests); + return; + } + + res.setHeader('set-cookie', 'c=' + (c + 1)); + res.setHeader('location', req.url); + res.statusCode = 302; + res.end('try again, i guess\n'); +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + jar: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 5'); + assert.equal(requests, 5); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-form.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-form.js new file mode 100644 index 000000000..91b9230d4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-form.js @@ -0,0 +1,79 @@ +var assert = require('assert') +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('../index'); +var fs = require('fs'); + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(8080, function() { + + var req = request.post('http://localhost:8080/upload', function () { + server.close(); + }) + var form = req.form() + + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-hawk.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-hawk.js new file mode 100755 index 000000000..845462580 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-hawk.js @@ -0,0 +1,33 @@ +var createServer = require('http').createServer + , request = require('../index') + , hawk = require('hawk') + , assert = require('assert') + ; + +var server = createServer(function (req, resp) { + + var getCred = function (id, callback) { + assert.equal(id, 'dh37fgj492je') + var credentials = + { key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn' + , algorithm: 'sha256' + , user: 'Steve' + } + return callback(null, credentials) + } + + hawk.server.authenticate(req, getCred, {}, function (err, credentials, attributes) { + resp.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' }) + resp.end(!err ? 'Hello ' + credentials.user : 'Shoosh!') + }) + +}) + +server.listen(8080, function () { + var creds = {key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', id:'dh37fgj492je'} + request('http://localhost:8080', {hawk:{credentials:creds}}, function (e, r, b) { + assert.equal(200, r.statusCode) + assert.equal(b, 'Hello Steve') + server.close() + }) +}) \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-headers.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-headers.js new file mode 100644 index 000000000..3982b9be0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , Cookie = require('cookie-jar') + , Jar = Cookie.Jar + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-http-signature.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-http-signature.js new file mode 100755 index 000000000..930047320 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-http-signature.js @@ -0,0 +1,106 @@ +var createServer = require('http').createServer + , request = require('../index') + , httpSignature = require('http-signature') + , assert = require('assert') + ; + +var privateKeyPEMs = {} + +privateKeyPEMs['key-1'] = + '-----BEGIN RSA PRIVATE KEY-----\n' + + 'MIIEpAIBAAKCAQEAzWSJl+Z9Bqv00FVL5N3+JCUoqmQPjIlya1BbeqQroNQ5yG1i\n' + + 'VbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9diDMnrzijAnYlTLOl84CK2vOxkj5b6\n' + + '8zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcuVi2lT9VjygFs1ILG4RyeX1BXUumu\n' + + 'Y8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u114wS7OQPigu6G99dpn/iPHa3zBm8\n' + + '7baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADPTdnO/SO+kvXy7fqd8atSn+HlQcx6\n' + + 'tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft2QIDAQABAoIBAG1exe3/LEBrPLfb\n' + + 'U8iRdY0lxFvHYIhDgIwohC3wUdMYb5SMurpNdEZn+7Sh/fkUVgp/GKJViu1mvh52\n' + + 'bKd2r52DwG9NQBQjVgkqY/auRYSglIPpr8PpYNSZlcneunCDGeqEY9hMmXc5Ssqs\n' + + 'PQYoEKKPN+IlDTg6PguDgAfLR4IUvt9KXVvmB/SSgV9tSeTy35LECt1Lq3ozbUgu\n' + + '30HZI3U6/7H+X22Pxxf8vzBtzkg5rRCLgv+OeNPo16xMnqbutt4TeqEkxRv5rtOo\n' + + '/A1i9khBeki0OJAFJsE82qnaSZodaRsxic59VnN8sWBwEKAt87tEu5A3K3j4XSDU\n' + + '/avZxAECgYEA+pS3DvpiQLtHlaO3nAH6MxHRrREOARXWRDe5nUQuUNpS1xq9wte6\n' + + 'DkFtba0UCvDLic08xvReTCbo9kH0y6zEy3zMpZuJlKbcWCkZf4S5miYPI0RTZtF8\n' + + 'yps6hWqzYFSiO9hMYws9k4OJLxX0x3sLK7iNZ32ujcSrkPBSiBr0gxkCgYEA0dWl\n' + + '637K41AJ/zy0FP0syq+r4eIkfqv+/t6y2aQVUBvxJYrj9ci6XHBqoxpDV8lufVYj\n' + + 'fUAfeI9/MZaWvQJRbnYLre0I6PJfLuCBIL5eflO77BGso165AF7QJZ+fwtgKv3zv\n' + + 'ZX75eudCSS/cFo0po9hlbcLMT4B82zEkgT8E2MECgYEAnz+3/wrdOmpLGiyL2dff\n' + + '3GjsqmJ2VfY8z+niSrI0BSpbD11tT9Ct67VlCBjA7hsOH6uRfpd6/kaUMzzDiFVq\n' + + 'VDAiFvV8QD6zNkwYalQ9aFvbrvwTTPrBpjl0vamMCiJ/YC0cjq1sGr2zh3sar1Ph\n' + + 'S43kP+s97dcZeelhaiJHVrECgYEAsx61q/loJ/LDFeYzs1cLTVn4V7I7hQY9fkOM\n' + + 'WM0AhInVqD6PqdfXfeFYpjJdGisQ7l0BnoGGW9vir+nkcyPvb2PFRIr6+B8tsU5j\n' + + '7BeVgjDoUfQkcrEBK5fEBtnj/ud9BUkY8oMZZBjVNLRuI7IMwZiPvMp0rcj4zAN/\n' + + 'LfUlpgECgYArBvFcBxSkNAzR3Rtteud1YDboSKluRM37Ey5plrn4BS0DD0jm++aD\n' + + '0pG2Hsik000hibw92lCkzvvBVAqF8BuAcnPlAeYfsOaa97PGEjSKEN5bJVWZ9/om\n' + + '9FV1axotRN2XWlwrhixZLEaagkREXhgQc540FS5O8IaI2Vpa80Atzg==\n' + + '-----END RSA PRIVATE KEY-----' + +var publicKeyPEMs = {} + +publicKeyPEMs['key-1'] = + '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWSJl+Z9Bqv00FVL5N3+\n' + + 'JCUoqmQPjIlya1BbeqQroNQ5yG1iVbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9di\n' + + 'DMnrzijAnYlTLOl84CK2vOxkj5b68zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcu\n' + + 'Vi2lT9VjygFs1ILG4RyeX1BXUumuY8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u1\n' + + '14wS7OQPigu6G99dpn/iPHa3zBm87baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADP\n' + + 'TdnO/SO+kvXy7fqd8atSn+HlQcx6tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft\n' + + '2QIDAQAB\n' + + '-----END PUBLIC KEY-----' + +publicKeyPEMs['key-2'] = + '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqp04VVr9OThli9b35Omz\n' + + 'VqSfWbsoQuRrgyWsrNRn3XkFmbWw4FzZwQ42OgGMzQ84Ta4d9zGKKQyFriTiPjPf\n' + + 'xhhrsaJnDuybcpVhcr7UNKjSZ0S59tU3hpRiEz6hO+Nc/OSSLkvalG0VKrxOln7J\n' + + 'LK/h3rNS/l6wDZ5S/KqsI6CYtV2ZLpn3ahLrizvEYNY038Qcm38qMWx+VJAvZ4di\n' + + 'qqmW7RLIsLT59SWmpXdhFKnkYYGhxrk1Mwl22dBTJNY5SbriU5G3gWgzYkm8pgHr\n' + + '6CtrXch9ciJAcDJehPrKXNvNDOdUh8EW3fekNJerF1lWcwQg44/12v8sDPyfbaKB\n' + + 'dQIDAQAB\n' + + '-----END PUBLIC KEY-----' + +var server = createServer(function (req, res) { + var parsed = httpSignature.parseRequest(req) + var publicKeyPEM = publicKeyPEMs[parsed.keyId] + var verified = httpSignature.verifySignature(parsed, publicKeyPEM) + res.writeHead(verified ? 200 : 400) + res.end() +}) + +server.listen(8080, function () { + function correctKeyTest(callback) { + var options = { + httpSignature: { + keyId: 'key-1', + key: privateKeyPEMs['key-1'] + } + } + request('http://localhost:8080', options, function (e, r, b) { + assert.equal(200, r.statusCode) + callback() + }) + } + + function incorrectKeyTest(callback) { + var options = { + httpSignature: { + keyId: 'key-2', + key: privateKeyPEMs['key-1'] + } + } + request('http://localhost:8080', options, function (e, r, b) { + assert.equal(400, r.statusCode) + callback() + }) + } + + var tests = [correctKeyTest, incorrectKeyTest] + var todo = tests.length; + for(var i = 0; i < tests.length; ++i) { + tests[i](function() { + if(!--todo) { + server.close() + } + }) + } +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-httpModule.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-httpModule.js new file mode 100644 index 000000000..2c19615f7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../index') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) { + if (er) throw er + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) { + if (er) throw er + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https-strict.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https-strict.js new file mode 100644 index 000000000..d49a9afcb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https.js new file mode 100644 index 000000000..b6858d433 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-https.js @@ -0,0 +1,87 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.rejectUnauthorized = false + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-isUrl.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-isUrl.js new file mode 100644 index 000000000..4a51ad018 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-isUrl.js @@ -0,0 +1,28 @@ +var assert = require('assert') + , request = require('../index') + , http = require('http') + ; + +var s = http.createServer(function(req, res) { + res.statusCode = 200; + res.end(''); +}).listen(6767, function () { + + // Test lowercase + request('http://localhost:6767', function (err, resp, body) { + // just need to get here without throwing an error + assert.equal(true, true); + }) + + // Test uppercase + request('HTTP://localhost:6767', function (err, resp, body) { + assert.equal(true, true); + }) + + // Test mixedcase + request('HtTp://localhost:6767', function (err, resp, body) { + assert.equal(true, true); + // clean up + s.close(); + }) +}) \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-localAddress.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-localAddress.js new file mode 100644 index 000000000..11a1bd125 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-localAddress.js @@ -0,0 +1,15 @@ +var request = require('../index') + , assert = require('assert') + ; + +request.get({ + uri: 'http://www.google.com', localAddress: '1.2.3.4' // some invalid address +}, function(err, res) { + assert(!res) // asserting that no response received +}) + +request.get({ + uri: 'http://www.google.com', localAddress: '127.0.0.1' +}, function(err, res) { + assert(!res) // asserting that no response received +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-oauth.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-oauth.js new file mode 100644 index 000000000..3269483d8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('oauth-sign').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../index') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-onelineproxy.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-onelineproxy.js new file mode 100644 index 000000000..c239f8921 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-onelineproxy.js @@ -0,0 +1,46 @@ +var http = require('http') + , assert = require('assert') + , request = require('../index') + ; + +var server = http.createServer(function (req, resp) { + resp.statusCode = 200 + if (req.url === '/get') { + assert.equal(req.method, 'GET') + resp.write('content') + resp.end() + return + } + if (req.url === '/put') { + var x = '' + assert.equal(req.method, 'PUT') + req.on('data', function (chunk) { + x += chunk + }) + req.on('end', function () { + assert.equal(x, 'content') + resp.write('success') + resp.end() + }) + return + } + if (req.url === '/proxy') { + assert.equal(req.method, 'PUT') + return req.pipe(request('http://localhost:8080/put')).pipe(resp) + } + + if (req.url === '/test') { + return request('http://localhost:8080/get').pipe(request.put('http://localhost:8080/proxy')).pipe(resp) + } + throw new Error('Unknown url', req.url) +}).listen(8080, function () { + request('http://localhost:8080/test', function (e, resp, body) { + if (e) throw e + if (resp.statusCode !== 200) throw new Error('statusCode not 200 ' + resp.statusCode) + assert.equal(body, 'success') + server.close() + }) +}) + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-params.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-params.js new file mode 100644 index 000000000..a5831a140 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-params.js @@ -0,0 +1,93 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + assert.notEqual(typeof test.callback, 'function') + console.log(1 + Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-piped-redirect.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-piped-redirect.js new file mode 100644 index 000000000..e295ec7fa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-piped-redirect.js @@ -0,0 +1,42 @@ +var http = require('http') + , assert = require('assert') + , request = require('../index') + ; + +var portOne = 8968 + , portTwo = 8969 + ; + + +// server one +var s1 = http.createServer(function (req, resp) { + if (req.url == '/original') { + resp.writeHeader(302, {'location': '/redirected'}) + resp.end() + } else if (req.url == '/redirected') { + resp.writeHeader(200, {'content-type': 'text/plain'}) + resp.write('OK') + resp.end() + } + +}).listen(portOne); + + +// server two +var s2 = http.createServer(function (req, resp) { + var x = request('http://localhost:'+portOne+'/original') + req.pipe(x) + x.pipe(resp) + +}).listen(portTwo, function () { + var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) { + assert.equal(body, 'OK') + + s1.close() + s2.close() + }); + + // it hangs, so wait a second :) + r.timeout = 1000; + +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pipes.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pipes.js new file mode 100644 index 000000000..52a15cc7e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pipes.js @@ -0,0 +1,216 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../index') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + // Test pipeing to a request object with a json body + s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json")); + + var mybodydata = new stream.Stream(); + mybodydata.readable = true + + counter++ + var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () { + check(); + }) + mybodydata.pipe(r2) + + mybodydata.emit('data', JSON.stringify({foo:"bar"})); + mybodydata.emit('end'); + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'application/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/jpeg'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.jpg')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.jpg')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.jpg')), fs.readFileSync(path.join(__dirname, 'test.jpg'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.jpg')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pool.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pool.js new file mode 100644 index 000000000..791ee8b93 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js new file mode 100644 index 000000000..7e83a41bd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js @@ -0,0 +1,61 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + + +var s = server.createServer() +var ss = server.createSSLServer() +var sUrl = 'http://localhost:' + s.port +var ssUrl = 'https://localhost:' + ss.port + +s.listen(s.port, bouncy(s, ssUrl)) +ss.listen(ss.port, bouncy(ss, sUrl)) + +var hits = {} +var expect = {} +var pending = 0 +function bouncy (s, server) { return function () { + + var redirs = { a: 'b' + , b: 'c' + , c: 'd' + , d: 'e' + , e: 'f' + , f: 'g' + , g: 'h' + , h: 'end' } + + var perm = true + Object.keys(redirs).forEach(function (p) { + var t = redirs[p] + + // switch type each time + var type = perm ? 301 : 302 + perm = !perm + s.on('/' + p, function (req, res) { + res.writeHead(type, { location: server + '/' + t }) + res.end() + }) + }) + + s.on('/end', function (req, res) { + var h = req.headers['x-test-key'] + hits[h] = true + pending -- + if (pending === 0) done() + }) +}} + +for (var i = 0; i < 5; i ++) { + pending ++ + var val = 'test_' + i + expect[val] = true + request({ url: (i % 2 ? sUrl : ssUrl) + '/a' + , headers: { 'x-test-key': val } + , rejectUnauthorized: false }) +} + +function done () { + assert.deepEqual(hits, expect) + process.exit(0) +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-proxy.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-proxy.js new file mode 100644 index 000000000..e183d68d1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../index') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-qs.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-qs.js new file mode 100644 index 000000000..65958e6a3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-qs.js @@ -0,0 +1,42 @@ +var request = request = require('../index') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) + +// Test giving empty qs property +var req5 = request.get({ uri: 'http://www.google.com', qs: {}}) +setTimeout(function(){ + assert.equal('/', req5.path) +}, 1) + + +// Test modifying the qs after creating the request +var req6 = request.get({ uri: 'http://www.google.com', qs: {}}); +req6.qs({ q: "test" }); +process.nextTick(function() { + assert.equal('/?q=test', req6.path); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-redirect.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-redirect.js new file mode 100644 index 000000000..cdd460666 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-redirect.js @@ -0,0 +1,155 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , Cookie = require('cookie-jar') + , Jar = Cookie.Jar + ; + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-s3.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-s3.js new file mode 100644 index 000000000..0f6a832b6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../index') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-timeout.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-timeout.js new file mode 100644 index 000000000..70363670f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-toJSON.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-toJSON.js new file mode 100644 index 000000000..6d5f92aaa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-tunnel.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-tunnel.js new file mode 100644 index 000000000..2ee3f393e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,75 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests|Accepting HTTP Socket connections/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('error', function (c) { + console.error('squid: error '+c) + if (c && !ready) { + notInstalled() + return + } +}) + +squid.on('exit', function (c) { + console.error('squid: exit '+c) + if (c && !ready) { + notInstalled() + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/' + , proxy: 'http://localhost:3128' + , strictSSL: true + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) + +function notInstalled() { + console.error('squid must be installed to run this test.') + console.error('skipping this test. please install squid and run again if you need to test tunneling.') + c = null + hadError = null + process.exit(0) +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/unicycle.jpg b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/unicycle.jpg new file mode 100644 index 000000000..7cea4dd71 Binary files /dev/null and b/node_modules/grunt-contrib-less/node_modules/less/node_modules/request/tests/unicycle.jpg differ diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.npmignore b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.npmignore new file mode 100644 index 000000000..3dddf3f67 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.travis.yml b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.travis.yml new file mode 100644 index 000000000..ddc9c4f98 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/CHANGELOG.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/CHANGELOG.md new file mode 100644 index 000000000..98b90d52b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,112 @@ +# Change Log + +## 0.1.31 + +* Delay parsing the mappings in SourceMapConsumer until queried for a source + location. + +* Support Sass source maps (which at the time of writing deviate from the spec + in small ways) in SourceMapConsumer. + +## 0.1.30 + +* Do not join source root with a source, when the source is a data URI. + +* Extend the test runner to allow running single specific test files at a time. + +* Performance improvements in `SourceNode.prototype.walk` and + `SourceMapConsumer.prototype.eachMapping`. + +* Source map browser builds will now work inside Workers. + +* Better error messages when attempting to add an invalid mapping to a + `SourceMapGenerator`. + +## 0.1.29 + +* Allow duplicate entries in the `names` and `sources` arrays of source maps + (usually from TypeScript) we are parsing. Fixes github isse 72. + +## 0.1.28 + +* Skip duplicate mappings when creating source maps from SourceNode; github + issue 75. + +## 0.1.27 + +* Don't throw an error when the `file` property is missing in SourceMapConsumer, + we don't use it anyway. + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. + diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/LICENSE new file mode 100644 index 000000000..ed1b7cf27 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/Makefile.dryice.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 000000000..d6fc26a79 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/README.md new file mode 100644 index 000000000..c20437bc6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/README.md @@ -0,0 +1,434 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +This library is written in the Asynchronous Module Definition format, and works +in the following environments: + +* Modern Browsers supporting ECMAScript 5 (either after the build, or with an + AMD loader such as RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Node + + $ npm install source-map + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should spew a bunch of stuff to stdout, and create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. + +## Examples + +### Consuming a source map + + var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + + var smc = new SourceMapConsumer(rawSourceMap); + + console.log(smc.sources); + // [ 'http://example.com/www/js/one.js', + // 'http://example.com/www/js/two.js' ] + + console.log(smc.originalPositionFor({ + line: 2, + column: 28 + })); + // { source: 'http://example.com/www/js/two.js', + // line: 2, + // column: 10, + // name: 'n' } + + console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 + })); + // { line: 2, column: 28 } + + smc.eachMapping(function (m) { + // ... + }); + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + + function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } + } + + var ast = parse("40 + 2", "add.js"); + console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' + })); + // { code: '40 + 2', + // map: [object SourceMapGenerator] } + +#### With SourceMapGenerator (low level API) + + var map = new SourceMapGenerator({ + file: "source-mapped.js" + }); + + map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" + }); + + console.log(map.toString()); + // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator(startOfSourceMap) + +To create a new one, you must pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: An optional root for all relative URLs in this source map. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used. + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode(line, column, source[, chunk[, name]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/assert-shim.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/assert-shim.js new file mode 100644 index 000000000..daa1a623c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/mini-require.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/mini-require.js new file mode 100644 index 000000000..0daf45377 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-source-map.jsm b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 000000000..ee2539d81 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-utils.jsm b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 000000000..80341d452 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-browser.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 000000000..fb29ff5fd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-source-map.jsm b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 000000000..cf3c2d8d3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-utils.jsm b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 000000000..b31b84cb6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-prefix.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-prefix.js new file mode 100644 index 000000000..1b13f300e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-suffix.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-suffix.js new file mode 100644 index 000000000..bec2de3f2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map.js new file mode 100644 index 000000000..121ad2416 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/array-set.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 000000000..40f9a18b1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,97 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64-vlq.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 000000000..1b67bb375 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,144 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 000000000..863cc4650 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/binary-search.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 000000000..ff347c68b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,81 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-consumer.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 000000000..a3b9dc086 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,477 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.slice() + .sort(util.compareByGeneratedPositions); + smc.__originalMappings = aSourceMap._mappings.slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-generator.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 000000000..48ead7ddc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,380 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.originalLine) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + orginal: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(util.compareByGeneratedPositions); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-node.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 000000000..626cb6574 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,371 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i] instanceof SourceNode) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/util.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 000000000..87946d3f7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,205 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + var dataUrlRegexp = /^data:.+\,.+/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/LICENSE new file mode 100644 index 000000000..f33d665de --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * 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. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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. + + + +MIT License +----------- + +Copyright (c) 2011, The Dojo Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/README.md new file mode 100644 index 000000000..c6995c072 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/README.md @@ -0,0 +1,171 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.1.0" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +### amdefine/intercept + +Consider this very experimental. + +Instead of pasting the piece of text for the amdefine setup of a `define` +variable in each module you create or consume, you can use `amdefine/intercept` +instead. It will automatically insert the above snippet in each .js file loaded +by Node. + +**Warning**: you should only use this if you are creating an application that +is consuming AMD style defined()'d modules that are distributed via npm and want +to run that code in Node. + +For library code where you are not sure if it will be used by others in Node or +in the browser, then explicitly depending on amdefine and placing the code +snippet above is suggested path, instead of using `amdefine/intercept`. The +intercept module affects all .js files loaded in the Node app, and it is +inconsiderate to modify global state like that unless you are also controlling +the top level app. + +#### Why distribute AMD-style nodes via npm? + +npm has a lot of weaknesses for front-end use (installed layout is not great, +should have better support for the `baseUrl + moduleID + '.js' style of loading, +single file JS installs), but some people want a JS package manager and are +willing to live with those constraints. If that is you, but still want to author +in AMD style modules to get dynamic require([]), better direct source usage and +powerful loader plugin support in the browser, then this tool can help. + +#### amdefine/intercept usage + +Just require it in your top level app module (for example index.js, server.js): + +```javascript +require('amdefine/intercept'); +``` + +The module does not return a value, so no need to assign the result to a local +variable. + +Then just require() code as you normally would with Node's require(). Any .js +loaded after the intercept require will have the amdefine check injected in +the .js source as it is loaded. It does not modify the source on disk, just +prepends some content to the text of the module as it is loaded by Node. + +#### How amdefine/intercept works + +It overrides the `Module._extensions['.js']` in Node to automatically prepend +the amdefine snippet above. So, it will affect any .js file loaded by your +app. + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration.
    + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +node all-intercept.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/amdefine.js new file mode 100644 index 000000000..53bf5a686 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/amdefine.js @@ -0,0 +1,299 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/intercept.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/intercept.js new file mode 100644 index 000000000..771a98301 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/intercept.js @@ -0,0 +1,36 @@ +/*jshint node: true */ +var inserted, + Module = require('module'), + fs = require('fs'), + existingExtFn = Module._extensions['.js'], + amdefineRegExp = /amdefine\.js/; + +inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; + +//From the node/lib/module.js source: +function stripBOM(content) { + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +//Also adapted from the node/lib/module.js source: +function intercept(module, filename) { + var content = stripBOM(fs.readFileSync(filename, 'utf8')); + + if (!amdefineRegExp.test(module.id)) { + content = inserted + content; + } + + module._compile(content, filename); +} + +intercept._id = 'amdefine/intercept'; + +if (!existingExtFn._id || existingExtFn._id !== intercept._id) { + Module._extensions['.js'] = intercept; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/package.json new file mode 100644 index 000000000..bb8e0d677 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/node_modules/amdefine/package.json @@ -0,0 +1,41 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "0.1.0", + "homepage": "http://github.com/jrburke/amdefine", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + }, + "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.1.0\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n### amdefine/intercept\n\nConsider this very experimental.\n\nInstead of pasting the piece of text for the amdefine setup of a `define`\nvariable in each module you create or consume, you can use `amdefine/intercept`\ninstead. It will automatically insert the above snippet in each .js file loaded\nby Node.\n\n**Warning**: you should only use this if you are creating an application that\nis consuming AMD style defined()'d modules that are distributed via npm and want\nto run that code in Node.\n\nFor library code where you are not sure if it will be used by others in Node or\nin the browser, then explicitly depending on amdefine and placing the code\nsnippet above is suggested path, instead of using `amdefine/intercept`. The\nintercept module affects all .js files loaded in the Node app, and it is\ninconsiderate to modify global state like that unless you are also controlling\nthe top level app.\n\n#### Why distribute AMD-style nodes via npm?\n\nnpm has a lot of weaknesses for front-end use (installed layout is not great,\nshould have better support for the `baseUrl + moduleID + '.js' style of loading,\nsingle file JS installs), but some people want a JS package manager and are\nwilling to live with those constraints. If that is you, but still want to author\nin AMD style modules to get dynamic require([]), better direct source usage and\npowerful loader plugin support in the browser, then this tool can help.\n\n#### amdefine/intercept usage\n\nJust require it in your top level app module (for example index.js, server.js):\n\n```javascript\nrequire('amdefine/intercept');\n```\n\nThe module does not return a value, so no need to assign the result to a local\nvariable.\n\nThen just require() code as you normally would with Node's require(). Any .js\nloaded after the intercept require will have the amdefine check injected in\nthe .js source as it is loaded. It does not modify the source on disk, just\nprepends some content to the text of the module as it is loaded by Node.\n\n#### How amdefine/intercept works\n\nIt overrides the `Module._extensions['.js']` in Node to automatically prepend\nthe amdefine snippet above. So, it will affect any .js file loaded by your\napp.\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\nnode all-intercept.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/jrburke/amdefine/issues" + }, + "_id": "amdefine@0.1.0", + "dist": { + "shasum": "83bf9967572ac1003f7dd965b10694ba6c624218" + }, + "_from": "amdefine@>=0.0.4", + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "scripts": {} +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/package.json b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/package.json new file mode 100644 index 000000000..6b2ec5d61 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/package.json @@ -0,0 +1,114 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.31", + "homepage": "https://github.com/mozilla/source-map", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Chase Douglas", + "email": "chase@newrelic.com" + }, + { + "name": "Evan Wallace", + "email": "evan.exe@gmail.com" + }, + { + "name": "Heather Arthur", + "email": "fayearthur@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js", + "build": "node Makefile.dryice.js" + }, + "readme": "# Source Map\n\nThis is a library to generate and consume the source map format\n[described here][format].\n\nThis library is written in the Asynchronous Module Definition format, and works\nin the following environments:\n\n* Modern Browsers supporting ECMAScript 5 (either after the build, or with an\n AMD loader such as RequireJS)\n\n* Inside Firefox (as a JSM file, after the build)\n\n* With NodeJS versions 0.8.X and higher\n\n## Node\n\n $ npm install source-map\n\n## Building from Source (for everywhere else)\n\nInstall Node and then run\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\nNext, run\n\n $ node Makefile.dryice.js\n\nThis should spew a bunch of stuff to stdout, and create the following files:\n\n* `dist/source-map.js` - The unminified browser version.\n\n* `dist/source-map.min.js` - The minified browser version.\n\n* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source.\n\n## Examples\n\n### Consuming a source map\n\n var rawSourceMap = {\n version: 3,\n file: 'min.js',\n names: ['bar', 'baz', 'n'],\n sources: ['one.js', 'two.js'],\n sourceRoot: 'http://example.com/www/js/',\n mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'\n };\n\n var smc = new SourceMapConsumer(rawSourceMap);\n\n console.log(smc.sources);\n // [ 'http://example.com/www/js/one.js',\n // 'http://example.com/www/js/two.js' ]\n\n console.log(smc.originalPositionFor({\n line: 2,\n column: 28\n }));\n // { source: 'http://example.com/www/js/two.js',\n // line: 2,\n // column: 10,\n // name: 'n' }\n\n console.log(smc.generatedPositionFor({\n source: 'http://example.com/www/js/two.js',\n line: 2,\n column: 10\n }));\n // { line: 2, column: 28 }\n\n smc.eachMapping(function (m) {\n // ...\n });\n\n### Generating a source map\n\nIn depth guide:\n[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/)\n\n#### With SourceNode (high level API)\n\n function compile(ast) {\n switch (ast.type) {\n case 'BinaryExpression':\n return new SourceNode(\n ast.location.line,\n ast.location.column,\n ast.location.source,\n [compile(ast.left), \" + \", compile(ast.right)]\n );\n case 'Literal':\n return new SourceNode(\n ast.location.line,\n ast.location.column,\n ast.location.source,\n String(ast.value)\n );\n // ...\n default:\n throw new Error(\"Bad AST\");\n }\n }\n\n var ast = parse(\"40 + 2\", \"add.js\");\n console.log(compile(ast).toStringWithSourceMap({\n file: 'add.js'\n }));\n // { code: '40 + 2',\n // map: [object SourceMapGenerator] }\n\n#### With SourceMapGenerator (low level API)\n\n var map = new SourceMapGenerator({\n file: \"source-mapped.js\"\n });\n\n map.addMapping({\n generated: {\n line: 10,\n column: 35\n },\n source: \"foo.js\",\n original: {\n line: 33,\n column: 2\n },\n name: \"christopher\"\n });\n\n console.log(map.toString());\n // '{\"version\":3,\"file\":\"source-mapped.js\",\"sources\":[\"foo.js\"],\"names\":[\"christopher\"],\"mappings\":\";;;;;;;;;mCAgCEA\"}'\n\n## API\n\nGet a reference to the module:\n\n // NodeJS\n var sourceMap = require('source-map');\n\n // Browser builds\n var sourceMap = window.sourceMap;\n\n // Inside Firefox\n let sourceMap = {};\n Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);\n\n### SourceMapConsumer\n\nA SourceMapConsumer instance represents a parsed source map which we can query\nfor information about the original file positions by giving it a file position\nin the generated source.\n\n#### new SourceMapConsumer(rawSourceMap)\n\nThe only parameter is the raw source map (either as a string which can be\n`JSON.parse`'d, or an object). According to the spec, source maps have the\nfollowing attributes:\n\n* `version`: Which version of the source map spec this map is following.\n\n* `sources`: An array of URLs to the original source files.\n\n* `names`: An array of identifiers which can be referrenced by individual\n mappings.\n\n* `sourceRoot`: Optional. The URL root from which all sources are relative.\n\n* `sourcesContent`: Optional. An array of contents of the original source files.\n\n* `mappings`: A string of base64 VLQs which contain the actual mappings.\n\n* `file`: The generated filename this source map is associated with.\n\n#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)\n\nReturns the original source, line, and column information for the generated\nsource's line and column positions provided. The only argument is an object with\nthe following properties:\n\n* `line`: The line number in the generated source.\n\n* `column`: The column number in the generated source.\n\nand an object is returned with the following properties:\n\n* `source`: The original source file, or null if this information is not\n available.\n\n* `line`: The line number in the original source, or null if this information is\n not available.\n\n* `column`: The column number in the original source, or null or null if this\n information is not available.\n\n* `name`: The original identifier, or null if this information is not available.\n\n#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)\n\nReturns the generated line and column information for the original source,\nline, and column positions provided. The only argument is an object with\nthe following properties:\n\n* `source`: The filename of the original source.\n\n* `line`: The line number in the original source.\n\n* `column`: The column number in the original source.\n\nand an object is returned with the following properties:\n\n* `line`: The line number in the generated source, or null.\n\n* `column`: The column number in the generated source, or null.\n\n#### SourceMapConsumer.prototype.sourceContentFor(source)\n\nReturns the original source content for the source provided. The only\nargument is the URL of the original source file.\n\n#### SourceMapConsumer.prototype.eachMapping(callback, context, order)\n\nIterate over each mapping between an original source/line/column and a\ngenerated line/column in this source map.\n\n* `callback`: The function that is called with each mapping. Mappings have the\n form `{ source, generatedLine, generatedColumn, originalLine, originalColumn,\n name }`\n\n* `context`: Optional. If specified, this object will be the value of `this`\n every time that `callback` is called.\n\n* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or\n `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over\n the mappings sorted by the generated file's line/column order or the\n original's source/line/column order, respectively. Defaults to\n `SourceMapConsumer.GENERATED_ORDER`.\n\n### SourceMapGenerator\n\nAn instance of the SourceMapGenerator represents a source map which is being\nbuilt incrementally.\n\n#### new SourceMapGenerator(startOfSourceMap)\n\nTo create a new one, you must pass an object with the following properties:\n\n* `file`: The filename of the generated source that this source map is\n associated with.\n\n* `sourceRoot`: An optional root for all relative URLs in this source map.\n\n#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)\n\nCreates a new SourceMapGenerator based on a SourceMapConsumer\n\n* `sourceMapConsumer` The SourceMap.\n\n#### SourceMapGenerator.prototype.addMapping(mapping)\n\nAdd a single mapping from original source line and column to the generated\nsource's line and column for this source map being created. The mapping object\nshould have the following properties:\n\n* `generated`: An object with the generated line and column positions.\n\n* `original`: An object with the original line and column positions.\n\n* `source`: The original source file (relative to the sourceRoot).\n\n* `name`: An optional original token name for this mapping.\n\n#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for an original source file.\n\n* `sourceFile` the URL of the original source file.\n\n* `sourceContent` the content of the source file.\n\n#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile])\n\nApplies a SourceMap for a source file to the SourceMap.\nEach mapping to the supplied source file is rewritten using the\nsupplied SourceMap. Note: The resolution for the resulting mappings\nis the minimium of this map and the supplied map.\n\n* `sourceMapConsumer`: The SourceMap to be applied.\n\n* `sourceFile`: Optional. The filename of the source file.\n If omitted, sourceMapConsumer.file will be used.\n\n#### SourceMapGenerator.prototype.toString()\n\nRenders the source map being generated to a string.\n\n### SourceNode\n\nSourceNodes provide a way to abstract over interpolating and/or concatenating\nsnippets of generated JavaScript source code, while maintaining the line and\ncolumn information associated between those snippets and the original source\ncode. This is useful as the final intermediate representation a compiler might\nuse before outputting the generated JS and source map.\n\n#### new SourceNode(line, column, source[, chunk[, name]])\n\n* `line`: The original line number associated with this source node, or null if\n it isn't associated with an original line.\n\n* `column`: The original column number associated with this source node, or null\n if it isn't associated with an original column.\n\n* `source`: The original source's filename.\n\n* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see\n below.\n\n* `name`: Optional. The original identifier.\n\n#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer)\n\nCreates a SourceNode from generated code and a SourceMapConsumer.\n\n* `code`: The generated code\n\n* `sourceMapConsumer` The SourceMap for the generated code\n\n#### SourceNode.prototype.add(chunk)\n\nAdd a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.prepend(chunk)\n\nPrepend a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for a source file. This will be added to the\n`SourceMap` in the `sourcesContent` field.\n\n* `sourceFile`: The filename of the source file\n\n* `sourceContent`: The content of the source file\n\n#### SourceNode.prototype.walk(fn)\n\nWalk over the tree of JS snippets in this node and its children. The walking\nfunction is called once for each snippet of JS and is passed that snippet and\nthe its original associated source's line/column location.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.walkSourceContents(fn)\n\nWalk over the tree of SourceNodes. The walking function is called for each\nsource file content and is passed the filename and source content.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.join(sep)\n\nLike `Array.prototype.join` except for SourceNodes. Inserts the separator\nbetween each of this source node's children.\n\n* `sep`: The separator.\n\n#### SourceNode.prototype.replaceRight(pattern, replacement)\n\nCall `String.prototype.replace` on the very right-most source snippet. Useful\nfor trimming whitespace from the end of a source node, etc.\n\n* `pattern`: The pattern to replace.\n\n* `replacement`: The thing to replace the pattern with.\n\n#### SourceNode.prototype.toString()\n\nReturn the string representation of this source node. Walks over the tree and\nconcatenates all the various snippets together to one string.\n\n### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap)\n\nReturns the string representation of this tree of source nodes, plus a\nSourceMapGenerator which contains all the mappings between the generated and\noriginal sources.\n\nThe arguments are the same as those to `new SourceMapGenerator`.\n\n## Tests\n\n[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)\n\nInstall NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.\n\nTo add new tests, create a new file named `test/test-.js`\nand export your test functions with names that start with \"test\", for example\n\n exports[\"test doing the foo bar\"] = function (assert, util) {\n ...\n };\n\nThe new test will be located automatically when you run the suite.\n\nThe `util` argument is the test utility module located at `test/source-map/util`.\n\nThe `assert` argument is a cut down version of node's assert module. You have\naccess to the following assertion functions:\n\n* `doesNotThrow`\n\n* `equal`\n\n* `ok`\n\n* `strictEqual`\n\n* `throws`\n\n(The reason for the restricted set of test functions is because we need the\ntests to run inside Firefox's test suite as well and so the assert module is\nshimmed in that environment. See `build/assert-shim.js`.)\n\n[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\n[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap\n[Dryice]: https://github.com/mozilla/dryice\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mozilla/source-map/issues" + }, + "_id": "source-map@0.1.31", + "dist": { + "shasum": "1eb3b2761d276d39c4ff5e4e4683e597d73b0701" + }, + "_from": "source-map@0.1.x", + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/run-tests.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/run-tests.js new file mode 100755 index 000000000..626c53f70 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/run-tests.js @@ -0,0 +1,71 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var failures = []; + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + } + catch (e) { + console.log('FAILED ' + tests[i].name + ': ' + k + '!'); + console.log(e.stack); + } + } + } + } + + console.log(""); + console.log(passed + ' / ' + total + ' tests passed.'); + console.log(""); + + failures.forEach(function (f) { + }); + + return failures.length; +} + +var code; + +process.stdout.on('close', function () { + process.exit(code); +}); + +function isTestFile(f) { + var testToRun = process.argv[2]; + return testToRun + ? path.basename(testToRun) === f + : /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')) + .filter(isTestFile) + .map(toModule); + +code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); +process.exit(code); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-api.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 000000000..3801233c0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 000000000..b5797edd5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,104 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + + exports['test .fromArray() with duplicates'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'foo']); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set = ArraySet.fromArray(['foo', 'foo'], true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + + exports['test .add() with duplicates'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + + set.add('foo'); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set.add('foo', true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 000000000..653a874e9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,24 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result; + for (var i = -255; i < 256; i++) { + result = base64VLQ.decode(base64VLQ.encode(i)); + assert.ok(result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 000000000..ff3a24456 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 000000000..ee306830d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), null); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 18); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 000000000..d831b9262 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,72 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + + // Fuzzy + + // Original to generated + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + + // Generated to original + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 000000000..f2c65a7f0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,451 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an objects'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var sources = map.sources; + + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var mapping; + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + + exports['test github issue #72, duplicate sources'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source1.js", "source1.js", "source3.js"], + "names": [], + "mappings": ";EAAC;;IAEE;;MEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.source, 'http://example.com/source3.js'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test github issue #72, duplicate names'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source.js"], + "names": ["name1", "name1", "name3"], + "mappings": ";EAACA;;IAEEA;;MAEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.name, 'name3'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { + var smg = new SourceMapGenerator({ + sourceRoot: 'http://example.com/', + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 4, column: 4 }, + source: 'baz.js', + name: 'dirtMcGirt' + }); + smg.setSourceContent('baz.js', 'baz.js content'); + + var smc = SourceMapConsumer.fromSourceMap(smg); + assert.equal(smc.file, 'foo.js'); + assert.equal(smc.sourceRoot, 'http://example.com/'); + assert.equal(smc.sources.length, 2); + assert.equal(smc.sources[0], 'http://example.com/bar.js'); + assert.equal(smc.sources[1], 'http://example.com/baz.js'); + assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); + + var pos = smc.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + assert.equal(pos.source, 'http://example.com/bar.js'); + assert.equal(pos.name, null); + + pos = smc.generatedPositionFor({ + line: 1, + column: 1, + source: 'http://example.com/bar.js' + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + pos = smc.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + assert.equal(pos.source, 'http://example.com/baz.js'); + assert.equal(pos.name, 'dirtMcGirt'); + + pos = smc.generatedPositionFor({ + line: 2, + column: 2, + source: 'http://example.com/baz.js' + }); + assert.equal(pos.line, 4); + assert.equal(pos.column, 4); + }; +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 000000000..ba292f548 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,417 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; + + exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: 'a.js', + name: 'foo' + }); + map.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 4, column: 4 }, + source: 'a.js', + name: 'foo' + }); + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: ['foo'], + mappings: 'CACEA;;GAEEA' + }); + }; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 000000000..6e0eca82d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,365 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }; + + exports['test .fromStringWithSourceMap()'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }; + + exports['test .fromStringWithSourceMap() empty map'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }; + + exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + "(function() {\n", + " var Test = {};\n", + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n", + "}());\n", + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }; + + exports['test .fromStringWithSourceMap() merging duplicate mappings'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function"), + new SourceNode(1, 0, "a.js", "() {\n"), + " ", + new SourceNode(1, 0, "a.js", "var Test = "), + new SourceNode(1, 0, "b.js", "{};\n"), + new SourceNode(2, 0, "b.js", "Test"), + new SourceNode(2, 0, "b.js", ".A", "A"), + new SourceNode(2, 20, "b.js", " = { value: 1234 };\n", "A"), + "}());\n", + "/* Generated Source */" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 2 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 13 }, + source: 'b.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'b.js', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 4 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 6 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 20 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, correctMap, inputMap); + }; + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/util.js b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/util.js new file mode 100644 index 000000000..288046bfa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,161 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, + "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/package.json b/node_modules/grunt-contrib-less/node_modules/less/package.json new file mode 100644 index 000000000..fdb41448d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/package.json @@ -0,0 +1,105 @@ +{ + "name": "less", + "version": "1.5.1", + "description": "Leaner CSS", + "homepage": "http://lesscss.org", + "author": { + "name": "Alexis Sellier", + "email": "self@cloudhead.net" + }, + "contributors": [ + { + "name": "The Core Less Team" + } + ], + "bugs": { + "url": "https://github.com/less/less.js/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/less/less.js.git" + }, + "licenses": [ + { + "type": "Apache v2", + "url": "https://github.com/less/less.js/blob/master/LICENSE" + } + ], + "bin": { + "lessc": "./bin/lessc" + }, + "main": "./lib/less/index", + "directories": { + "test": "./test" + }, + "jam": { + "main": "./dist/less-1.5.0.js" + }, + "engines": { + "node": ">=0.4.2" + }, + "scripts": { + "test": "grunt test" + }, + "optionalDependencies": { + "mime": "1.2.x", + "request": ">=2.12.0", + "mkdirp": "~0.3.5", + "clean-css": "2.0.x", + "source-map": "0.1.x" + }, + "devDependencies": { + "diff": "~1.0", + "grunt": "~0.4.1", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-connect": "~0.3.0", + "grunt-contrib-jasmine": "~0.5.2", + "grunt-contrib-jshint": "~0.7.2", + "grunt-contrib-uglify": "~0.2.7", + "grunt-shell": "~0.3.1", + "http-server": "~0.5.5", + "matchdep": "~0.1.2", + "time-grunt": "~0.1.1" + }, + "keywords": [ + "compile less", + "css nesting", + "css variable", + "css", + "gradients css", + "gradients css3", + "less compiler", + "less css", + "less mixins", + "less", + "less.js", + "lesscss", + "mixins", + "nested css", + "parser", + "preprocessor", + "bootstrap css", + "bootstrap less", + "style", + "styles", + "stylesheet", + "variables in css", + "css less" + ], + "readme": "# [Less.js v1.5.1](http://lesscss.org)\r\n\r\n> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).\r\n\r\nThis is the JavaScript, and now official, stable version of LESS.\r\n\r\n\r\n## Getting Started\r\n\r\nOptions for adding Less.js to your project:\r\n\r\n* Install with [NPM](https://npmjs.org/): `npm install less`\r\n* [Download the latest release][download]\r\n* Clone the repo: `git clone git://github.com/less/less.js.git`\r\n\r\n\r\n\r\n## Feature Highlights\r\nLESS extends CSS with dynamic features such as:\r\n\r\n* [nesting](#nesting)\r\n* [variables](#variables)\r\n* [operations](#operations)\r\n* [mixins](#mixins)\r\n* [extend](#extend) (selector inheritance)\r\n\r\nTo learn about the many other features Less.js has to offer please visit [http://lesscss.org](http://lesscss.org) and [the Less.js wiki][wiki]\r\n\r\n\r\n### Examples\r\n#### nesting\r\nTake advantage of nesting to make code more readable and maintainable. This:\r\n\r\n```less\r\n.nav > li > a {\r\n border: 1px solid #f5f5f5;\r\n &:hover {\r\n border-color: #ddd;\r\n }\r\n}\r\n```\r\n\r\nrenders to:\r\n\r\n```css\r\n.nav > li > a {\r\n border: 1px solid #f5f5f5;\r\n}\r\n.nav > li > a:hover {\r\n border-color: #ddd;\r\n}\r\n```\r\n\r\n\r\n#### variables\r\nUpdated commonly used values from a single location.\r\n\r\n```less\r\n// Variables (\"inline\" comments like this can be used)\r\n@link-color: #428bca; // appears as \"sea blue\"\r\n\r\n/* Or \"block comments\" that span\r\n multiple lines, like this */\r\na {\r\n color: @link-color; // use the variable in styles\r\n}\r\n```\r\n\r\nVariables can also be used in `@import` statements, URLs, selector names, and more.\r\n\r\n\r\n\r\n#### operations\r\nContinuing with the same example above, we can use our variables even easier to maintain with _operations_, which enables the use of addition, subraction, multiplication and division in your styles:\r\n\r\n```less\r\n// Variables\r\n@link-color: #428bca;\r\n@link-color-hover: darken(@link-color, 10%);\r\n\r\n// Styles\r\na {\r\n color: @link-color;\r\n}\r\na:hover {\r\n color: @link-color-hover;\r\n}\r\n```\r\nrenders to:\r\n\r\n```css\r\na {\r\n color: #428bca;\r\n}\r\na:hover {\r\n color: #3071a9;\r\n}\r\n```\r\n\r\n#### mixins\r\n##### \"implicit\" mixins\r\nMixins enable you to apply the styles of one selector inside another selector like this:\r\n\r\n```less\r\n// Any \"regular\" class...\r\n.link {\r\n color: @link-color;\r\n}\r\na {\r\n font-weight: bold;\r\n .link; // ...can be used as an \"implicit\" mixin\r\n}\r\n```\r\n\r\nrenders to:\r\n\r\n```css\r\n.link {\r\n color: #428bca;\r\n}\r\na {\r\n font-weight: bold;\r\n color: #428bca;\r\n}\r\n```\r\n\r\nSo any selector can be an \"implicit mixin\". We'll show you a DRYer way to do this below.\r\n\r\n\r\n\r\n##### parametric mixins\r\nMixins can also accept parameters:\r\n\r\n```less\r\n// Transition mixin\r\n.transition(@transition) {\r\n -webkit-transition: @transition;\r\n -moz-transition: @transition;\r\n -o-transition: @transition;\r\n transition: @transition;\r\n}\r\n```\r\n\r\nused like this:\r\n\r\n```less\r\na {\r\n font-weight: bold;\r\n color: @link-color;\r\n .transition(color .2s ease-in-out);\r\n // Hover state\r\n &:hover {\r\n color: @link-color-hover;\r\n }\r\n}\r\n```\r\n\r\nrenders to:\r\n\r\n```css\r\na {\r\n font-weight: bold;\r\n color: #428bca;\r\n -webkit-transition: color 0.2s ease-in-out;\r\n -moz-transition: color 0.2s ease-in-out;\r\n -o-transition: color 0.2s ease-in-out;\r\n transition: color 0.2s ease-in-out;\r\n}\r\na:hover {\r\n color: #3071a9;\r\n}\r\n```\r\n\r\n\r\n#### extend\r\nThe `extend` feature can be thought of as the _inverse_ of mixins. It accomplishes the goal of \"borrowing styles\", but rather than copying all the rules of _Selector A_ over to _Selector B_, `extend` copies the name of the _inheriting selector_ (_Selector B_) over to the _extending selector_ (_Selector A_). So continuing with the example used for [mixins](#mixins) above, extend works like this:\r\n\r\n```less\r\n.link {\r\n color: @link-color;\r\n}\r\na:extend(.link) {\r\n font-weight: bold;\r\n}\r\n// Can also be written as\r\na {\r\n &:extend(.link);\r\n font-weight: bold;\r\n}\r\n```\r\n\r\nrenders to:\r\n\r\n```css\r\n.link, a {\r\n color: #428bca;\r\n}\r\n```\r\n\r\n## Usage\r\n\r\n### Compiling and Parsing\r\nInvoke the compiler from node:\r\n\r\n```javascript\r\nvar less = require('less');\r\n\r\nless.render('.class { width: (1 + 1) }', function (e, css) {\r\n console.log(css);\r\n});\r\n```\r\n\r\nOutputs:\r\n\r\n```css\r\n.class {\r\n width: 2;\r\n}\r\n```\r\n\r\nYou may also manually invoke the parser and compiler:\r\n\r\n```javascript\r\nvar parser = new(less.Parser);\r\n\r\nparser.parse('.class { width: (1 + 1) }', function (err, tree) {\r\n if (err) { return console.error(err) }\r\n console.log(tree.toCSS());\r\n});\r\n```\r\n\r\n\r\n### Configuration\r\nYou may also pass options to the compiler:\r\n\r\n```javascript\r\nvar parser = new(less.Parser)({\r\n paths: ['.', './src/less'], // Specify search paths for @import directives\r\n filename: 'style.less' // Specify a filename, for better error messages\r\n});\r\n\r\nparser.parse('.class { width: (1 + 1) }', function (e, tree) {\r\n tree.toCSS({ compress: true }); // Minify CSS output\r\n});\r\n```\r\n\r\n## More information\r\n\r\nFor general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org) or [the less wiki][wiki].\r\n\r\nHere are other resources for using Less.js:\r\n\r\n* [stackoverflow.com][so] is a great place to get answers about Less.\r\n* [node.js tools](https://github.com/less/less.js/wiki/Converting-LESS-to-CSS) for converting Less to CSS\r\n* [GUI compilers for Less](https://github.com/less/less.js/wiki/GUI-compilers-that-use-LESS.js)\r\n* [Less.js Issues][issues] for reporting bugs\r\n\r\n\r\n\r\n## Contributing\r\nPlease read [CONTRIBUTING.md](./CONTRIBUTING.md). Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\r\n\r\n### Reporting Issues\r\n\r\nBefore opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/). After that if you find a bug or would like to make feature request, [please open a new issue][issues].\r\n\r\n\r\n\r\n### Development\r\n\r\n#### Install Less.js\r\n\r\nStart by either [downloading this project][download] manually, or in the command line:\r\n\r\n```shell\r\ngit clone https://github.com/less/less.js.git \"less\"\r\n```\r\nand then `cd less`.\r\n\r\n\r\n#### Install dependencies\r\n\r\nTo install all the dependencies for less development, run:\r\n\r\n```shell\r\nnpm install\r\n```\r\n\r\nIf you haven't run grunt before, install grunt-cli globally so you can just run `grunt`\r\n\r\n```shell\r\nnpm install grunt-cli -g\r\n```\r\n\r\nYou should now be able to build Less.js, run tests, benchmarking, and other tasks listed in the Gruntfile.\r\n\r\n## Using Less.js Grunt\r\n\r\nTests, benchmarking and building is done using Grunt `~0.4.1`. If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to install and use Grunt plugins, which are necessary for development with Less.js.\r\n\r\nThe Less.js [Gruntfile](Gruntfile.js) is configured with the following \"convenience tasks\" :\r\n\r\n#### test - `grunt`\r\nRuns jshint, nodeunit and headless jasmine tests using [phantomjs](http://code.google.com/p/phantomjs/). You must have phantomjs installed for the jasmine tests to run.\r\n\r\n#### test - `grunt benchmark`\r\nRuns the benchmark suite.\r\n\r\n#### build for testing browser - 'grunt browser'\r\nThis builds less.js and puts it in 'test/browser/less.js'\r\n\r\n#### build - `grunt stable | grunt beta | grunt alpha`\r\nBuilds Less.js from from the `/lib/less` source files. This is done by the developer releasing a new release, do not do this if you are creating a pull request.\r\n\r\n#### readme - `grunt readme`\r\nBuild the README file from [a template](build/README.md) to ensure that metadata is up-to-date and (more likely to be) correct.\r\n\r\nPlease review the [Gruntfile](Gruntfile.js) to become acquainted with the other available tasks.\r\n\r\n**Please note** that if you have any issues installing dependencies or running any of the Gruntfile commands, please make sure to uninstall any previous versions, both in the local node_modules directory, and clear your global npm cache, and then try running `npm install` again. After that if you still have issues, please let us know about it so we can help.\r\n\r\n\r\n## Release History\r\nSee the [changelog](CHANGELOG)\r\n\r\n## [License](LICENSE)\r\n\r\nCopyright (c) 2009-2013 [Alexis Sellier](http://cloudhead.io/) & The Core Less Team\r\nLicensed under the [Apache License](LICENSE).\r\n\r\n\r\n[so]: http://stackoverflow.com/questions/tagged/twitter-bootstrap+less \"StackOverflow.com\"\r\n[issues]: https://github.com/less/less.js/issues \"GitHub Issues for Less.js\"\r\n[wiki]: https://github.com/less/less.js/wiki \"The official wiki for Less.js\"\r\n[download]: https://github.com/less/less.js/zipball/master \"Download Less.js\"", + "readmeFilename": "README.md", + "dependencies": { + "mime": "1.2.x", + "request": ">=2.12.0", + "mkdirp": "~0.3.5", + "clean-css": "2.0.x", + "source-map": "0.1.x" + }, + "_id": "less@1.5.1", + "dist": { + "shasum": "c4389ba8445d624cfe190b854679c3eb3220842f" + }, + "_from": "less@~1.5.0", + "_resolved": "https://registry.npmjs.org/less/-/less-1.5.1.tgz" +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/projectFilesBackup/.idea/libraries/sass_stdlib.xml b/node_modules/grunt-contrib-less/node_modules/less/projectFilesBackup/.idea/libraries/sass_stdlib.xml new file mode 100644 index 000000000..8962a7d07 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/projectFilesBackup/.idea/libraries/sass_stdlib.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/common.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/common.js new file mode 100644 index 000000000..785c2a201 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/common.js @@ -0,0 +1,201 @@ +/* record log messages for testing */ +// var logAllIds = function() { +// var allTags = document.head.getElementsByTagName('style'); +// var ids = []; +// for (var tg = 0; tg < allTags.length; tg++) { +// var tag = allTags[tg]; +// if (tag.id) { +// console.log(tag.id); +// } +// } +// }; + +var logMessages = [], + realConsoleLog = console.log; +console.log = function(msg) { + logMessages.push(msg); + realConsoleLog.call(console, msg); +}; + +var testLessEqualsInDocument = function() { + testLessInDocument(testSheet); +}; + +var testLessErrorsInDocument = function(isConsole) { + testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet); +}; + +var testLessInDocument = function(testFunc) { + var links = document.getElementsByTagName('link'), + typePattern = /^text\/(x-)?less$/; + + for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + testFunc(links[i]); + } + } +}; + +var testSheet = function(sheet) { + it(sheet.id + " should match the expected output", function() { + var lessOutputId = sheet.id.replace("original-", ""), + expectedOutputId = "expected-" + lessOutputId, + lessOutputObj, + lessOutput, + expectedOutputHref = document.getElementById(expectedOutputId).href, + expectedOutput = loadFile(expectedOutputHref); + + // Browser spec generates less on the fly, so we need to loose control + waitsFor(function() { + lessOutputObj = document.getElementById(lessOutputId); + // the type condition is necessary because of inline browser tests + return lessOutputObj !== null && lessOutputObj.type === "text/css"; + }, "generation of " + lessOutputId + "", 700); + + runs(function() { + lessOutput = lessOutputObj.innerText; + }); + + waitsFor(function() { + return expectedOutput.loaded; + }, "failed to load expected outout", 10000); + + runs(function() { + // use sheet to do testing + expect(expectedOutput.text).toEqual(lessOutput); + }); + }); +}; + +//TODO: do it cleaner - the same way as in css + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain + .replace(/^\//, '') // Remove root / + .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +var testErrorSheet = function(sheet) { + it(sheet.id + " should match an error", function() { + var lessHref = sheet.href, + id = "less-error-message:" + extractId(lessHref), + // id = sheet.id.replace(/^original-less:/, "less-error-message:"), + errorHref = lessHref.replace(/.less$/, ".txt"), + errorFile = loadFile(errorHref), + actualErrorElement, + actualErrorMsg; + + // Less.js sets 10ms timer in order to add error message on top of page. + waitsFor(function() { + actualErrorElement = document.getElementById(id); + return actualErrorElement !== null; + }, "error message was not generated", 70); + + runs(function() { + actualErrorMsg = actualErrorElement.innerText + .replace(/\n\d+/g, function(lineNo) { + return lineNo + " "; + }) + .replace(/\n\s*in /g, " in ") + .replace("\n\n", "\n"); + }); + + waitsFor(function() { + return errorFile.loaded; + }, "failed to load expected outout", 10000); + + runs(function() { + var errorTxt = errorFile.text + .replace("{path}", "") + .replace("{pathrel}", "") + .replace("{pathhref}", "http://localhost:8081/test/less/errors/") + .replace("{404status}", " (404)"); + expect(errorTxt).toEqual(actualErrorMsg); + if (errorTxt == actualErrorMsg) { + actualErrorElement.style.display = "none"; + } + }); + }); +}; + +var testErrorSheetConsole = function(sheet) { + it(sheet.id + " should match an error", function() { + var lessHref = sheet.href, + id = sheet.id.replace(/^original-less:/, "less-error-message:"), + errorHref = lessHref.replace(/.less$/, ".txt"), + errorFile = loadFile(errorHref), + actualErrorElement = document.getElementById(id), + actualErrorMsg = logMessages[logMessages.length - 1]; + + describe("the error", function() { + expect(actualErrorElement).toBe(null); + + }); + + /*actualErrorMsg = actualErrorElement.innerText + .replace(/\n\d+/g, function(lineNo) { return lineNo + " "; }) + .replace(/\n\s*in /g, " in ") + .replace("\n\n", "\n");*/ + + waitsFor(function() { + return errorFile.loaded; + }, "failed to load expected outout", 10000); + + runs(function() { + var errorTxt = errorFile.text + .replace("{path}", "") + .replace("{pathrel}", "") + .replace("{pathhref}", "http://localhost:8081/browser/less/") + .replace("{404status}", " (404)") + .trim(); + expect(errorTxt).toEqual(actualErrorMsg); + }); + }); +}; + +var loadFile = function(href) { + var request = new XMLHttpRequest(), + response = { + loaded: false, + text: "" + }; + request.open('GET', href, true); + request.onload = function(e) { + response.text = request.response.replace(/\r/g, ""); + response.loaded = true; + }; + request.send(); + return response; +}; + +(function() { + var jasmineEnv = jasmine.getEnv(); + jasmineEnv.updateInterval = 1000; + + var htmlReporter = new jasmine.HtmlReporter(); + + jasmineEnv.addReporter(htmlReporter); + + jasmineEnv.specFilter = function(spec) { + return htmlReporter.specFilter(spec); + }; + + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + execJasmine(); + }; + + function execJasmine() { + setTimeout(function() { + jasmineEnv.execute(); + }, 3000); + } + +})(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/global-vars/simple.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/global-vars/simple.css new file mode 100644 index 000000000..05b9fb02f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/global-vars/simple.css @@ -0,0 +1,3 @@ +.test { + color: #ff0000; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/modify-vars/simple.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/modify-vars/simple.css new file mode 100644 index 000000000..4cb81bac6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/modify-vars/simple.css @@ -0,0 +1,7 @@ +.testisimported { + color: gainsboro; +} +.test { + color1: #008000; + color2: #800080; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/relative-urls/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/relative-urls/urls.css new file mode 100644 index 000000000..891d5977b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/relative-urls/urls.css @@ -0,0 +1,35 @@ +@import "http://localhost:8081/test/browser/less/imports/modify-this.css"; +@import "http://localhost:8081/test/browser/less/imports/modify-again.css"; +.modify { + my-url: url("http://localhost:8081/test/browser/less/imports/a.png"); +} +.modify { + my-url: url("http://localhost:8081/test/browser/less/imports/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/relative-urls/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(http://localhost:8081/test/browser/less/relative-urls/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(http://localhost:8081/test/browser/less/relative-urls/bg.jpg) no-repeat, url(http://localhost:8081/test/browser/less/relative-urls/bg.png) repeat-x top left, url(http://localhost:8081/test/browser/less/relative-urls/bg); +} +.values { + url: url('http://localhost:8081/test/browser/less/relative-urls/Trebuchet'); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath-relative/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath-relative/urls.css new file mode 100644 index 000000000..20b08339d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath-relative/urls.css @@ -0,0 +1,35 @@ +@import "https://www.github.com/cloudhead/imports/modify-this.css"; +@import "https://www.github.com/cloudhead/imports/modify-again.css"; +.modify { + my-url: url("https://www.github.com/cloudhead/imports/a.png"); +} +.modify { + my-url: url("https://www.github.com/cloudhead/imports/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(https://www.github.com/cloudhead/less.js/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(https://www.github.com/cloudhead/less.js/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(https://www.github.com/cloudhead/less.js/bg.jpg) no-repeat, url(https://www.github.com/cloudhead/less.js/bg.png) repeat-x top left, url(https://www.github.com/cloudhead/less.js/bg); +} +.values { + url: url('https://www.github.com/cloudhead/less.js/Trebuchet'); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath/urls.css new file mode 100644 index 000000000..9618e8e50 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/rootpath/urls.css @@ -0,0 +1,35 @@ +@import "https://www.github.com/modify-this.css"; +@import "https://www.github.com/modify-again.css"; +.modify { + my-url: url("https://www.github.com/a.png"); +} +.modify { + my-url: url("https://www.github.com/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(https://www.github.com/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(https://www.github.com/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(https://www.github.com/bg.jpg) no-repeat, url(https://www.github.com/bg.png) repeat-x top left, url(https://www.github.com/bg); +} +.values { + url: url('https://www.github.com/Trebuchet'); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/urls.css new file mode 100644 index 000000000..c15105127 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/css/urls.css @@ -0,0 +1,53 @@ +@import "http://localhost:8081/test/browser/less/modify-this.css"; +@import "http://localhost:8081/test/browser/less/modify-again.css"; +.modify { + my-url: url("http://localhost:8081/test/browser/less/a.png"); +} +.modify { + my-url: url("http://localhost:8081/test/browser/less/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(http://localhost:8081/test/browser/less/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(http://localhost:8081/test/browser/less/bg.jpg) no-repeat, url(http://localhost:8081/test/browser/less/bg.png) repeat-x top left, url(http://localhost:8081/test/browser/less/bg); +} +.values { + url: url('http://localhost:8081/test/browser/less/Trebuchet'); +} +#data-uri { + uri: url('http://localhost:8081/test/data/image.jpg'); +} +#data-uri-guess { + uri: url('http://localhost:8081/test/data/image.jpg'); +} +#data-uri-ascii { + uri-1: url('http://localhost:8081/test/data/page.html'); + uri-2: url('http://localhost:8081/test/data/page.html'); +} +#data-uri-toobig { + uri: url('http://localhost:8081/test/data/data-uri-fail.png'); +} +#svg-functions { + background-image: url('data:image/svg+xml,'); + background-image: url('data:image/svg+xml,'); + background-image: url('data:image/svg+xml,'); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/es5.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/es5.js new file mode 100644 index 000000000..c4fcc8023 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/es5.js @@ -0,0 +1,27 @@ +/* + PhantomJS does not implement bind. this is from + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind + */ +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + }; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine-html.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine-html.js new file mode 100644 index 000000000..543d56963 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine-html.js @@ -0,0 +1,681 @@ +jasmine.HtmlReporterHelpers = {}; + +jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { + var results = child.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + + return status; +}; + +jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { + var parentDiv = this.dom.summary; + var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; + var parent = child[parentSuite]; + + if (parent) { + if (typeof this.views.suites[parent.id] == 'undefined') { + this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); + } + parentDiv = this.views.suites[parent.id].element; + } + + parentDiv.appendChild(childElement); +}; + + +jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { + for(var fn in jasmine.HtmlReporterHelpers) { + ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; + } +}; + +jasmine.HtmlReporter = function(_doc) { + var self = this; + var doc = _doc || window.document; + + var reporterView; + + var dom = {}; + + // Jasmine Reporter Public Interface + self.logRunningSpecs = false; + + self.reportRunnerStarting = function(runner) { + var specs = runner.specs() || []; + + if (specs.length == 0) { + return; + } + + createReporterDom(runner.env.versionString()); + doc.body.appendChild(dom.reporter); + setExceptionHandling(); + + reporterView = new jasmine.HtmlReporter.ReporterView(dom); + reporterView.addSpecs(specs, self.specFilter); + }; + + self.reportRunnerResults = function(runner) { + reporterView && reporterView.complete(); + }; + + self.reportSuiteResults = function(suite) { + reporterView.suiteComplete(suite); + }; + + self.reportSpecStarting = function(spec) { + if (self.logRunningSpecs) { + self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } + }; + + self.reportSpecResults = function(spec) { + reporterView.specComplete(spec); + }; + + self.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } + }; + + self.specFilter = function(spec) { + if (!focusedSpecName()) { + return true; + } + + return spec.getFullName().indexOf(focusedSpecName()) === 0; + }; + + return self; + + function focusedSpecName() { + var specName; + + (function memoizeFocusedSpec() { + if (specName) { + return; + } + + var paramMap = []; + var params = jasmine.HtmlReporter.parameters(doc); + + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + specName = paramMap.spec; + })(); + + return specName; + } + + function createReporterDom(version) { + dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, + dom.banner = self.createDom('div', { className: 'banner' }, + self.createDom('span', { className: 'title' }, "Jasmine "), + self.createDom('span', { className: 'version' }, version)), + + dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), + dom.alert = self.createDom('div', {className: 'alert'}, + self.createDom('span', { className: 'exceptions' }, + self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'), + self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))), + dom.results = self.createDom('div', {className: 'results'}, + dom.summary = self.createDom('div', { className: 'summary' }), + dom.details = self.createDom('div', { id: 'details' })) + ); + } + + function noTryCatch() { + return window.location.search.match(/catch=false/); + } + + function searchWithCatch() { + var params = jasmine.HtmlReporter.parameters(window.document); + var removed = false; + var i = 0; + + while (!removed && i < params.length) { + if (params[i].match(/catch=/)) { + params.splice(i, 1); + removed = true; + } + i++; + } + if (jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + + return params.join("&"); + } + + function setExceptionHandling() { + var chxCatch = document.getElementById('no_try_catch'); + + if (noTryCatch()) { + chxCatch.setAttribute('checked', true); + jasmine.CATCH_EXCEPTIONS = false; + } + chxCatch.onclick = function() { + window.location.search = searchWithCatch(); + }; + } +}; +jasmine.HtmlReporter.parameters = function(doc) { + var paramStr = doc.location.search.substring(1); + var params = []; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + } + return params; +} +jasmine.HtmlReporter.sectionLink = function(sectionName) { + var link = '?'; + var params = []; + + if (sectionName) { + params.push('spec=' + encodeURIComponent(sectionName)); + } + if (!jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + if (params.length > 0) { + link += params.join("&"); + } + + return link; +}; +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter); +jasmine.HtmlReporter.ReporterView = function(dom) { + this.startedAt = new Date(); + this.runningSpecCount = 0; + this.completeSpecCount = 0; + this.passedCount = 0; + this.failedCount = 0; + this.skippedCount = 0; + + this.createResultsMenu = function() { + this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, + this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), + ' | ', + this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); + + this.summaryMenuItem.onclick = function() { + dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); + }; + + this.detailsMenuItem.onclick = function() { + showDetails(); + }; + }; + + this.addSpecs = function(specs, specFilter) { + this.totalSpecCount = specs.length; + + this.views = { + specs: {}, + suites: {} + }; + + for (var i = 0; i < specs.length; i++) { + var spec = specs[i]; + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); + if (specFilter(spec)) { + this.runningSpecCount++; + } + } + }; + + this.specComplete = function(spec) { + this.completeSpecCount++; + + if (isUndefined(this.views.specs[spec.id])) { + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); + } + + var specView = this.views.specs[spec.id]; + + switch (specView.status()) { + case 'passed': + this.passedCount++; + break; + + case 'failed': + this.failedCount++; + break; + + case 'skipped': + this.skippedCount++; + break; + } + + specView.refresh(); + this.refresh(); + }; + + this.suiteComplete = function(suite) { + var suiteView = this.views.suites[suite.id]; + if (isUndefined(suiteView)) { + return; + } + suiteView.refresh(); + }; + + this.refresh = function() { + + if (isUndefined(this.resultsMenu)) { + this.createResultsMenu(); + } + + // currently running UI + if (isUndefined(this.runningAlert)) { + this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" }); + dom.alert.appendChild(this.runningAlert); + } + this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); + + // skipped specs UI + if (isUndefined(this.skippedAlert)) { + this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); + } + + this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.skippedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.skippedAlert); + } + + // passing specs UI + if (isUndefined(this.passedAlert)) { + this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); + } + this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); + + // failing specs UI + if (isUndefined(this.failedAlert)) { + this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); + } + this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); + + if (this.failedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.failedAlert); + dom.alert.appendChild(this.resultsMenu); + } + + // summary info + this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); + this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; + }; + + this.complete = function() { + dom.alert.removeChild(this.runningAlert); + + this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.failedCount === 0) { + dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); + } else { + showDetails(); + } + + dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); + }; + + return this; + + function showDetails() { + if (dom.reporter.className.search(/showDetails/) === -1) { + dom.reporter.className += " showDetails"; + } + } + + function isUndefined(obj) { + return typeof obj === 'undefined'; + } + + function isDefined(obj) { + return !isUndefined(obj); + } + + function specPluralizedFor(count) { + var str = count + " spec"; + if (count > 1) { + str += "s" + } + return str; + } + +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); + + +jasmine.HtmlReporter.SpecView = function(spec, dom, views) { + this.spec = spec; + this.dom = dom; + this.views = views; + + this.symbol = this.createDom('li', { className: 'pending' }); + this.dom.symbolSummary.appendChild(this.symbol); + + this.summary = this.createDom('div', { className: 'specSummary' }, + this.createDom('a', { + className: 'description', + href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.description) + ); + + this.detail = this.createDom('div', { className: 'specDetail' }, + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.getFullName()) + ); +}; + +jasmine.HtmlReporter.SpecView.prototype.status = function() { + return this.getSpecStatus(this.spec); +}; + +jasmine.HtmlReporter.SpecView.prototype.refresh = function() { + this.symbol.className = this.status(); + + switch (this.status()) { + case 'skipped': + break; + + case 'passed': + this.appendSummaryToSuiteDiv(); + break; + + case 'failed': + this.appendSummaryToSuiteDiv(); + this.appendFailureDetail(); + break; + } +}; + +jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { + this.summary.className += ' ' + this.status(); + this.appendToSummary(this.spec, this.summary); +}; + +jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { + this.detail.className += ' ' + this.status(); + + var resultItems = this.spec.results().getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + this.detail.appendChild(messagesDiv); + this.dom.details.appendChild(this.detail); + } +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { + this.suite = suite; + this.dom = dom; + this.views = views; + + this.element = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) + ); + + this.appendToSummary(this.suite, this.element); +}; + +jasmine.HtmlReporter.SuiteView.prototype.status = function() { + return this.getSpecStatus(this.suite); +}; + +jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { + this.element.className += " " + this.status(); +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); + +/* @deprecated Use jasmine.HtmlReporter instead + */ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.css b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.css new file mode 100644 index 000000000..8c008dc72 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.css @@ -0,0 +1,82 @@ +body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } + +#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +#HTMLReporter a { text-decoration: none; } +#HTMLReporter a:hover { text-decoration: underline; } +#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } +#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } +#HTMLReporter #jasmine_content { position: fixed; right: 100%; } +#HTMLReporter .version { color: #aaaaaa; } +#HTMLReporter .banner { margin-top: 14px; } +#HTMLReporter .duration { color: #aaaaaa; float: right; } +#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } +#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } +#HTMLReporter .symbolSummary li.passed { font-size: 14px; } +#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } +#HTMLReporter .symbolSummary li.failed { line-height: 9px; } +#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } +#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } +#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } +#HTMLReporter .symbolSummary li.pending { line-height: 11px; } +#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } +#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +#HTMLReporter .runningAlert { background-color: #666666; } +#HTMLReporter .skippedAlert { background-color: #aaaaaa; } +#HTMLReporter .skippedAlert:first-child { background-color: #333333; } +#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } +#HTMLReporter .passingAlert { background-color: #a6b779; } +#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } +#HTMLReporter .failingAlert { background-color: #cf867e; } +#HTMLReporter .failingAlert:first-child { background-color: #b03911; } +#HTMLReporter .results { margin-top: 14px; } +#HTMLReporter #details { display: none; } +#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } +#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter.showDetails .summary { display: none; } +#HTMLReporter.showDetails #details { display: block; } +#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter .summary { margin-top: 14px; } +#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } +#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } +#HTMLReporter .summary .specSummary.failed a { color: #b03911; } +#HTMLReporter .description + .suite { margin-top: 0; } +#HTMLReporter .suite { margin-top: 14px; } +#HTMLReporter .suite a { color: #333333; } +#HTMLReporter #details .specDetail { margin-bottom: 28px; } +#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } +#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } +#HTMLReporter .resultMessage span.result { display: block; } +#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } + +#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } +#TrivialReporter a:visited, #TrivialReporter a { color: #303; } +#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } +#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } +#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } +#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } +#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } +#TrivialReporter .runner.running { background-color: yellow; } +#TrivialReporter .options { text-align: right; font-size: .8em; } +#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } +#TrivialReporter .suite .suite { margin: 5px; } +#TrivialReporter .suite.passed { background-color: #dfd; } +#TrivialReporter .suite.failed { background-color: #fdd; } +#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } +#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } +#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } +#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } +#TrivialReporter .spec.skipped { background-color: #bbb; } +#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } +#TrivialReporter .passed { background-color: #cfc; display: none; } +#TrivialReporter .failed { background-color: #fbb; } +#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } +#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } +#TrivialReporter .resultMessage .mismatch { color: black; } +#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } +#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } +#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } +#TrivialReporter #jasmine_content { position: fixed; right: 100%; } +#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.js new file mode 100644 index 000000000..6b3459b91 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/jasmine.js @@ -0,0 +1,2600 @@ +var isCommonJS = typeof window == "undefined" && typeof exports == "object"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Maximum levels of nesting that will be included when an object is pretty-printed + */ +jasmine.MAX_PRETTY_PRINT_DEPTH = 40; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +/** + * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite. + * Set to false to let the exception bubble up in the browser. + * + */ +jasmine.CATCH_EXCEPTIONS = true; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + * @return {jasmine.Matchers} + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.source != b.source) + mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/"); + + if (a.ignoreCase != b.ignoreCase) + mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.global != b.global) + mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.multiline != b.multiline) + mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.sticky != b.sticky) + mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier"); + + return (mismatchValues.length === 0); +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a.jasmineMatches) { + return a.jasmineMatches(b); + } + + if (b.jasmineMatches) { + return b.jasmineMatches(a); + } + + if (a instanceof jasmine.Matchers.ObjectContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.ObjectContaining) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (a instanceof RegExp && b instanceof RegExp) { + return this.compareRegExps_(a, b, mismatchKeys, mismatchValues); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + if (!jasmine.CATCH_EXCEPTIONS) { + this.func.apply(this.spec); + } + else { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that compares the actual to NaN. + */ +jasmine.Matchers.prototype.toBeNaN = function() { + this.message = function() { + return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ]; + }; + + return (this.actual !== this.actual); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."; + var positiveMessage = ""; + if (this.actual.callCount === 0) { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; + } else { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '') + } + return [positiveMessage, invertedMessage]; + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision, as number of decimal places + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2); +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} [expected] + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineToString = function() { + return ''; +}; + +jasmine.Matchers.ObjectContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { + return ""; +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!obj.hasOwnProperty(property)) continue; + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Array"); + return; + } + + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Object"); + return; + } + + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + + // parallel to blocks. each true value in this array means the block will + // get executed even if we abort + this.ensured = []; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.unshift(block); + this.ensured.unshift(ensure); +}; + +jasmine.Queue.prototype.add = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.push(block); + this.ensured.push(ensure); +}; + +jasmine.Queue.prototype.insertNext = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.ensured.splice((this.index + this.offset + 1), 0, ensure); + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this), true); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 3, + "build": 1, + "revision": 1354556913 +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less.js new file mode 100644 index 000000000..8e670e041 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less.js @@ -0,0 +1,6937 @@ +/*! + * LESS - Leaner CSS v1.5.0 + * http://lesscss.org + * + * Copyright (c) 2009-2013, Alexis Sellier + * Licensed under the Apache v2 License. + * + * @licence + */ + + + +(function (window, undefined) {// +// Stub out `require` in the browser +// +function require(arg) { + return window.less[arg.split('/')[1]]; +}; + + +if (typeof(window.less) === 'undefined' || typeof(window.less.nodeType) !== 'undefined') { window.less = {}; } +less = window.less; +tree = window.less.tree = {}; +less.mode = 'browser'; + +var less, tree; + +// Node.js does not have a header file added which defines less +if (less === undefined) { + less = exports; + tree = require('./tree'); + less.mode = 'node'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser, + rootFilename = env && env.filename; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed around by reference. + if (!(env instanceof tree.parseEnv)) { + env = new tree.parseEnv(env); + } + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, currentFileInfo, importOptions, callback) { + var parserImports = this; + this.queue.push(path); + + var fileParsedFunc = function (e, root, fullPath) { + parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue + + var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename; + + parserImports.files[fullPath] = root; // Store the root + + if (e && !parserImports.error) { parserImports.error = e; } + + callback(e, root, importedPreviously, fullPath); + }; + + if (less.Parser.importer) { + less.Parser.importer(path, currentFileInfo, fileParsedFunc, env); + } else { + less.Parser.fileLoader(path, currentFileInfo, function(e, contents, fullPath, newFileInfo) { + if (e) {fileParsedFunc(e); return;} + + var newEnv = new tree.parseEnv(env); + + newEnv.currentFileInfo = newFileInfo; + newEnv.processImports = false; + newEnv.contents[fullPath] = contents; + + if (currentFileInfo.reference || importOptions.reference) { + newFileInfo.reference = true; + } + + if (importOptions.inline) { + fileParsedFunc(null, contents, fullPath); + } else { + new(less.Parser)(newEnv).parse(contents, function (e, root) { + fileParsedFunc(e, root, fullPath); + }); + } + }, env); + } + } + }; + + function save() { temp = chunks[j], memo = i, current = i; } + function restore() { chunks[j] = temp, i = memo, current = i; } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, length; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break; } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return tok.test(chunks[j]); + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, inputStream) { + var n = index + 1, + line = null, + column = -1; + + while (--n >= 0 && inputStream.charAt(n) !== '\n') { + column++; + } + + if (typeof index === 'number') { + line = (inputStream.slice(0, index).match(/\n/g) || "").length; + } + + return { + line: line, + column: column + }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + callLine = e.call && getLocation(e.call, input).line, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = callLine + 1; + this.callExtract = lines[callLine]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, line, lines, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + parser.imports.contents[env.currentFileInfo.filename] = input; + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': + if (!inParam) { + level++; + chunk.push(c); + break; + } + /* falls through */ + case '}': + if (!inParam) { + level--; + chunk.push(c); + chunks[++j] = chunk = []; + break; + } + /* falls through */ + case '(': + if (!inParam) { + inParam = true; + chunk.push(c); + break; + } + /* falls through */ + case ')': + if (inParam) { + inParam = false; + chunk.push(c); + break; + } + /* falls through */ + default: + chunk.push(c); + } + + i++; + } + if (level !== 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join(''); }); + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + return function (options, variables) { + options = options || {}; + var evaldRoot, + css, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, null, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + new(tree.toCSSVisitor)({compress: Boolean(options.compress)}) + .run(evaldRoot); + + if (options.sourceMap) { + evaldRoot = new tree.sourceMapOutput( + { + writeSourceMap: options.writeSourceMap, + rootNode: evaldRoot, + contentsMap: parser.imports.contents, + sourceMapFilename: options.sourceMapFilename, + outputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath, + outputSourceFiles: options.outputSourceFiles, + sourceMapGenerator: options.sourceMapGenerator + }); + } + + css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.cleancss && less.mode === 'node') { + var CleanCSS = require('clean-css'); + //TODO would be nice for no advanced to be an option + return new CleanCSS({keepSpecialComments: '*', processImport: false, noRebase: true, noAdvanced: true}).minify(css); + } else if (options.compress) { + return css.replace(/(^(\s)+)|((\s)+$)/g, ""); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + var loc = getLocation(i, input); + lines = input.split('\n'); + line = loc.line + 1; + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: loc.column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + return callback(e); + } + else { + return callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + return finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') { return; } + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true, i, env.currentFileInfo); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment, false, i, env.currentFileInfo); + } + }, + + comments: function () { + var comment, comments = []; + + while(comment = $(this.comment)) { + comments.push(comment); + } + + return comments; + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true; } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { return; } + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + var color = tree.Color.fromKeyword(k); + if (color) { + return color; + } + return new(tree.Keyword)(k); + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) { return; } + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null; } + else { i += name.length; } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { + break; + } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) { + return; + } + + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + /*jshint eqnull:true */ + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) { + return; + } + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings + if (input.charAt(j) !== '`') { return; } + if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) { + error("You are using JavaScript, which has been disabled."); + } + + if (e) { $('~'); } + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")); + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return; } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i, env.currentFileInfo)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comments); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) { + return; + } + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comments); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) { return; } + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i, env.currentFileInfo); } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++; } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + // + // A CSS selector (see selector below) + // with less extensions e.g. the ability to extend and guard + // + lessSelector: function () { + return this.selector(true); + }, + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function (isLess) { + var e, elements = [], c, extend, extendList = [], when, condition; + + while ((isLess && (extend = $(this.extend))) || (isLess && (when = $(/^when/))) || (e = $(this.element))) { + if (when) { + condition = expect(this.conditions, 'expected condition'); + } else if (condition) { + error("CSS guard can only be used at the end of selector"); + } else if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e); + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { + break; + } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList, condition, i, env.currentFileInfo); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var key, val, op; + + if (! $('[')) { return; } + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[0-9]+%/) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + while (s = $(this.lessSelector)) { + selectors.push(s); + $(this.comments); + if (! $(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + $(this.comments); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) { + ruleset.debugInfo = debugInfo; + } + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important, merge = false; + save(); + + if (c === '.' || c === '#' || c === '&') { return; } + + if (name = $(this.variable) || $(this.ruleProperty)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + + important = $(this.important); + if (name[name.length-1] === "+") { + merge = true; + name = name.substr(0, name.length - 1); + } + + if (value && $(this.end)) { + return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break; } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once|inline|reference)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = ($(this.entities.keyword) || $(this.entities.variable))) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null; } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break; } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break; } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + media.debugInfo = debugInfo; + } + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression, identifier; + + if (input.charAt(i) !== '@') { return; } + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) { return; } + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@host": + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + identifier = ($(/^[^{]+/) || '').trim(); + if (identifier) { + name += " " + identifier; + } + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules, i, env.currentFileInfo); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = []; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while (peek(/^,\s*(not\s*)?\(/) && $(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true; } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|<=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-'); } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = []; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + }, + ruleProperty: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*(\+?)\s*:/)) { + return name[1] + (name[2] || ""); + } + } + } + }; +}; + + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; } + else if (h * 2 < 1) { return m2; } + else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; } + else { return m1; } + } + + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + // filter: saturate(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + /*jshint loopfunc:true */ + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + if(!(val instanceof tree.Dimension)) { + throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") }; + } + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + /*jshint eqnull:true */ + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + _minmax: function (isMin, args) { + args = Array.prototype.slice.call(args); + switch(args.length) { + case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 1: return args[0]; + } + var i, j, current, currentUnified, referenceUnified, unit, + order = [], // elems only contains original argument values. + values = {}; // key is the unit.toString() for unified tree.Dimension values, + // value is the index into the order array. + for (i = 0; i < args.length; i++) { + current = args[i]; + if (!(current instanceof tree.Dimension)) { + order.push(current); + continue; + } + currentUnified = current.unify(); + unit = currentUnified.unit.toString(); + j = values[unit]; + if (j === undefined) { + values[unit] = order.length; + order.push(current); + continue; + } + referenceUnified = order[j].unify(); + if ( isMin && currentUnified.value < referenceUnified.value || + !isMin && currentUnified.value > referenceUnified.value) { + order[j] = current; + } + } + if (order.length == 1) { + return order[0]; + } + args = order.map(function (a) { return a.toCSS(this.env); }) + .join(this.env.compress ? "," : ", "); + return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")"); + }, + min: function () { + return this._minmax(true, arguments); + }, + max: function () { + return this._minmax(false, arguments); + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + var colorCandidate = n.value, + returnColor; + returnColor = tree.Color.fromKeyword(colorCandidate); + if (returnColor) { + return returnColor; + } + if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) { + return new(tree.Color)(colorCandidate.slice(1)); + } + throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" }; + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + // handle non-array values as an array of length 1 + // return 'undefined' if index is invalid + return Array.isArray(values.value) + ? values.value[index] : Array(values)[index]; + }, + length: function(values) { + var n = Array.isArray(values.value) ? values.value.length : 1; + return new tree.Dimension(n); + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) { mimetype += ';base64'; } + } + else { + useBase64 = /;base64$/.test(mimetype); + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + }, + + "svg-gradient": function(direction) { + + function throwArgumentDescriptor() { + throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" }; + } + + if (arguments.length < 3) { + throwArgumentDescriptor(); + } + var stops = Array.prototype.slice.call(arguments, 1), + gradientDirectionSvg, + gradientType = "linear", + rectangleDimension = 'x="0" y="0" width="1" height="1"', + useBase64 = true, + renderEnv = {compress: false}, + returner, + directionValue = direction.toCSS(renderEnv), + i, color, position, positionValue, alpha; + + switch (directionValue) { + case "to bottom": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; + break; + case "to right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; + break; + case "to bottom right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; + break; + case "to top right": + gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; + break; + case "ellipse": + case "ellipse at center": + gradientType = "radial"; + gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; + rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; + break; + default: + throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" }; + } + returner = '' + + '' + + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; + + for (i = 0; i < stops.length; i+= 1) { + if (stops[i].value) { + color = stops[i].value[0]; + position = stops[i].value[1]; + } else { + color = stops[i]; + position = undefined; + } + + if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) { + throwArgumentDescriptor(); + } + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + alpha = color.alpha; + returner += ''; + } + returner += '' + + ''; + + if (useBase64) { + // only works in node, needs interface to what is supported in environment + try { + returner = new Buffer(returner).toString('base64'); + } catch(e) { + useBase64 = false; + } + } + + returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'"; + return new(tree.URL)(new(tree.Anonymous)(returner)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + /*jshint eqnull:true */ + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); + +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); + +(function (tree) { + +tree.debugInfo = function(env, ctx, lineSeperator) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) { + if (a == '\\') { + a = '\/'; + } + return '\\' + a; + }) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r; } + } + return null; +}; + +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +tree.toCSS = function (env) { + var strs = []; + this.genCSS(env, { + add: function(chunk, fileInfo, index) { + strs.push(chunk); + }, + isEmpty: function () { + return strs.length === 0; + } + }); + return strs.join(''); +}; + +tree.outputRuleset = function (env, output, rules) { + output.add((env.compress ? '{' : ' {\n')); + env.tabLevel = (env.tabLevel || 0) + 1; + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + for(var i = 0; i < rules.length; i++) { + output.add(tabRuleStr); + rules[i].genCSS(env, output); + output.add(env.compress ? '' : '\n'); + } + env.tabLevel--; + output.add(tabSetStr + "}"); +}; + +})(require('./tree')); + +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); } + return this; + }, + genCSS: function (env, output) { + output.add("alpha(opacity="); + + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + + output.add(")"); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Anonymous = function (string, index, currentFileInfo, mapLines) { + this.value = string.value || string; + this.index = index; + this.mapLines = mapLines; + this.currentFileInfo = currentFileInfo; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + eval: function () { return this; }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + }, + genCSS: function (env, output) { + output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add(this.key + '='); + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + /*jshint eqnull:true */ + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + return new tree.Call(this.name, args, this.index, this.currentFileInfo); + }, + + genCSS: function (env, output) { + output.add(this.name + "(", this.currentFileInfo, this.index); + + for(var i = 0; i < this.args.length; i++) { + this.args[i].genCSS(env, output); + if (i + 1 < this.args.length) { + output.add(", "); + } + } + + output.add(")"); + }, + + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; + +var transparentKeyword = "transparent"; + +tree.Color.prototype = { + type: "Color", + eval: function () { return this; }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + if (this.alpha < 1.0) { + if (this.alpha === 0 && this.isTransparentKeyword) { + return transparentKeyword; + } + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.toRGB(); + + if (compress) { + var splitcolor = color.split(''); + + // Convert color to short format + if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) { + color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5]; + } + } + + return color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toRGB: function () { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + +tree.Color.fromKeyword = function(keyword) { + if (tree.colors.hasOwnProperty(keyword)) { + // detect named color + return new(tree.Color)(tree.colors[keyword].slice(1)); + } + if (keyword === transparentKeyword) { + var transparent = new(tree.Color)([0, 0, 0], 0); + transparent.isTransparentKeyword = true; + return transparent; + } +}; + + +})(require('../tree')); + +(function (tree) { + +tree.Comment = function (value, silent, index, currentFileInfo) { + this.value = value; + this.silent = !!silent; + this.currentFileInfo = currentFileInfo; +}; +tree.Comment.prototype = { + type: "Comment", + genCSS: function (env, output) { + if (this.debugInfo) { + output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index); + } + output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n + }, + toCSS: tree.toCSS, + isSilent: function(env) { + var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced), + isCompressed = env.compress && !this.value.match(/^\/\*!/); + return this.silent || isReference || isCompressed; + }, + eval: function () { return this; }, + markReferenced: function () { + this.isReferenced = true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<' || op === '<='; + case 0: return op === '=' || op === '>=' || op === '=<' || op === '<='; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); + +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + genCSS: function (env, output) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && this.unit.isLength()) { + output.add(strValue); + return; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + output.add(strValue); + this.unit.genCSS(env, output); + }, + toCSS: tree.toCSS, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + /*jshint noempty:false */ + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, targetUnit, derivedConversions = {}, applyUnit; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + applyUnit = function (atomicUnit, denominator) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(applyUnit); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + genCSS: function (env, output) { + if (this.numerator.length >= 1) { + output.add(this.numerator[0]); + } else + if (this.denominator.length >= 1) { + output.add(this.denominator[0]); + } else + if ((!env || !env.strictUnits) && this.backupUnit) { + output.add(this.backupUnit); + } + }, + toCSS: tree.toCSS, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isLength: function () { + return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/)); + }, + + isEmpty: function () { + return this.numerator.length === 0 && this.denominator.length === 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length === 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, result = {}, mapUnit; + + mapUnit = function (atomicUnit) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }; + + for (var groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(mapUnit); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Directive = function (name, value, index, currentFileInfo) { + this.name = name; + + if (Array.isArray(value)) { + this.rules = [new(tree.Ruleset)([], value)]; + this.rules[0].allowImports = true; + } else { + this.value = value; + } + this.currentFileInfo = currentFileInfo; + +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.rules = visitor.visit(this.rules); + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name, this.currentFileInfo, this.index); + if (this.rules) { + tree.outputRuleset(env, output, this.rules); + } else { + output.add(' '); + this.value.genCSS(env, output); + output.add(';'); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var evaldDirective = this; + if (this.rules) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo); + evaldDirective.rules = [this.rules[0].eval(env)]; + evaldDirective.rules[0].root = true; + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + markReferenced: function () { + var i, rules; + this.isReferenced = true; + if (this.rules) { + rules = this.rules[0].rules; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Element = function (combinator, value, index, currentFileInfo) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index, + this.currentFileInfo); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env), this.currentFileInfo, this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value === '' && this.combinator.value.charAt(0) === '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + _outputMap: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : ' + ', + '~' : ' ~ ', + '>' : ' > ', + '|' : '|' + }, + _outputMapCompressed: { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : '+', + '~' : '~', + '>' : '>', + '|' : '|' + }, + genCSS: function (env, output) { + output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]); + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + genCSS: function (env, output) { + for(var i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add(" "); + } + } + }, + toCSS: tree.toCSS, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i, + selectorElements; + + for(i = 0; i < selectors.length; i++) { + selectorElements = selectors[i].elements; + // duplicate the logic in genCSS function inside the selector node. + // future TODO - move both logics into the selector joiner visitor + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + selectorElements[0].combinator.value = ' '; + } + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); + +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined || this.options.inline) { + this.css = !this.options.less || this.options.inline; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + if (!this.options.inline) { + this.root = visitor.visit(this.root); + } + }, + genCSS: function (env, output) { + if (this.css) { + output.add("@import ", this.currentFileInfo, this.index); + this.path.genCSS(env, output); + if (this.features) { + output.add(" "); + this.features.genCSS(env, output); + } + output.add(';'); + } + }, + toCSS: tree.toCSS, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + + if (!(path instanceof tree.URL)) { + if (rootpath) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + path.value = env.normalizePath(path.value); + } + + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.options.inline) { + //todo needs to reference css file not import + var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true); + return this.features ? new(tree.Media)([contents], this.features.value) : [contents]; + } else if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + /*jshint loopfunc:true */ + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Keyword = function (value) { this.value = value; }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); + +(function (tree) { + +tree.Media = function (value, features, index, currentFileInfo) { + this.index = index; + this.currentFileInfo = currentFileInfo; + + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.rules = [new(tree.Ruleset)(selectors, value)]; + this.rules[0].allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.rules = visitor.visit(this.rules); + }, + genCSS: function (env, output) { + output.add('@media ', this.currentFileInfo, this.index); + this.features.genCSS(env, output); + tree.outputRuleset(env, output, this.rules); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], [], this.index, this.currentFileInfo); + if(this.debugInfo) { + this.rules[0].debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.rules[0]); + media.rules = [this.rules[0].eval(env)]; + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env); + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); }, + find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', this.index, this.currentFileInfo); + return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)]; + }, + markReferenced: function () { + var i, rules = this.rules[0].rules; + this.isReferenced = true; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])]; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + if (!(mixin instanceof tree.mixin.Definition)) { + mixin = new tree.mixin.Definition("", [], mixin.rules, null, false); + mixin.originalRuleset = mixins[m].originalRuleset || mixins[m]; + } + //if (this.important) { + // isImportant = env.isImportant; + // env.isImportant = true; + //} + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + //if (this.important) { + // env.isImportant = isImportant; + //} + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + if (!this.currentFileInfo || !this.currentFileInfo.reference) { + for (i = 0; i < rules.length; i++) { + rule = rules[i]; + if (rule.markReferenced) { + rule.markReferenced(); + } + } + } + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1; } + else { return count; } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + /*jshint boss:true */ + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) { continue; } + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + rules, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules); + ruleset.originalRuleset = this; + ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames))); + if (important) { + ruleset = this.parent.makeImportant.apply(ruleset); + } + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables + .concat(this.frames) // the parent namespace/mixin frames + .concat(env.frames)))) { // the current environment frames + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (! this.variadic) { + if (argsLength < this.required) { return false; } + if (argsLength > this.params.length) { return false; } + } else { + if (argsLength < (this.required - 1)) { return false; } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('-'); + this.value.genCSS(env, output); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + genCSS: function (env, output) { + this.operands[0].genCSS(env, output); + if (this.isSpaced) { + output.add(" "); + } + output.add(this.op); + if (this.isSpaced) { + output.add(" "); + } + this.operands[1].genCSS(env, output); + }, + toCSS: tree.toCSS +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('('); + this.value.genCSS(env, output); + output.add(')'); + }, + toCSS: tree.toCSS, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + genCSS: function (env, output) { + if (!this.escaped) { + output.add(this.quote, this.currentFileInfo, this.index); + } + output.add(this.value); + if (!this.escaped) { + output.add(this.quote); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (name.charAt(0) === '@'); +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index); + try { + this.value.genCSS(env, output); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index); + }, + toCSS: tree.toCSS, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.merge, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.merge, + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + if (this.paths) { + for(var i = 0; i < this.paths.length; i++) { + this.paths[i] = visitor.visit(this.paths[i]); + } + } else { + this.selectors = visitor.visit(this.selectors); + } + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env); }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + var rule; + var i; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + /*jshint loopfunc:true */ + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (i = 0; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + matchCondition: function (args, env) { + var lastSelector = this.selectors[this.selectors.length-1]; + if (lastSelector.condition && + !lastSelector.condition.eval( + new(tree.evalEnv)(env, + env.frames))) { + return false; + } + return true; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables; } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key]; } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > match) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(match)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + genCSS: function (env, output) { + var i, j, + ruleNodes = [], + rulesetNodes = [], + debugInfo, // Line number debugging + rule, + firstRuleset = true, + path; + + env.tabLevel = (env.tabLevel || 0); + + if (!this.root) { + env.tabLevel++; + } + + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "); + + for (i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + if (rule.rules || (rule instanceof tree.Media) || rule instanceof tree.Directive || (this.root && rule instanceof tree.Comment)) { + rulesetNodes.push(rule); + } else { + ruleNodes.push(rule); + } + } + + // If this is the root node, we don't render + // a selector, or {}. + if (!this.root) { + debugInfo = tree.debugInfo(env, this, tabSetStr); + + if (debugInfo) { + output.add(debugInfo); + output.add(tabSetStr); + } + + for(i = 0; i < this.paths.length; i++) { + path = this.paths[i]; + env.firstSelector = true; + for(j = 0; j < path.length; j++) { + path[j].genCSS(env, output); + env.firstSelector = false; + } + if (i + 1 < this.paths.length) { + output.add(env.compress ? ',' : (',\n' + tabSetStr)); + } + } + + output.add((env.compress ? '{' : ' {\n') + tabRuleStr); + } + + // Compile rules and rulesets + for (i = 0; i < ruleNodes.length; i++) { + rule = ruleNodes[i]; + + // @page{ directive ends up with root elements inside it, a mix of rules and rulesets + // In this instance we do not know whether it is the last property + if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) { + env.lastRule = true; + } + + if (rule.genCSS) { + rule.genCSS(env, output); + } else if (rule.value) { + output.add(rule.value.toString()); + } + + if (!env.lastRule) { + output.add(env.compress ? '' : ('\n' + tabRuleStr)); + } else { + env.lastRule = false; + } + } + + if (!this.root) { + output.add((env.compress ? '}' : '\n' + tabSetStr + '}')); + env.tabLevel--; + } + + for (i = 0; i < rulesetNodes.length; i++) { + if (ruleNodes.length && firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + if (!firstRuleset) { + output.add((env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr)); + } + firstRuleset = false; + rulesetNodes[i].genCSS(env, output); + } + + if (!output.isEmpty() && !env.compress && this.firstRoot) { + output.add('\n'); + } + }, + + toCSS: tree.toCSS, + + markReferenced: function () { + for (var s = 0; s < this.selectors.length; s++) { + this.selectors[s].markReferenced(); + } + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for (i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for (j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length === 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0, el.index, el.currentFileInfo)); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for (k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = selector.createDerived([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for (i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel; + + if (selectors.length === 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for (i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); + +(function (tree) { + +tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) { + this.elements = elements; + this.extendList = extendList || []; + this.condition = condition; + this.currentFileInfo = currentFileInfo || {}; + this.isReferenced = isReferenced; + if (!condition) { + this.evaldCondition = true; + } +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList); + this.condition = visitor.visit(this.condition); + }, + createDerived: function(elements, extendList, evaldCondition) { + /*jshint eqnull:true */ + evaldCondition = evaldCondition != null ? evaldCondition : this.evaldCondition; + var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced); + newSelector.evaldCondition = evaldCondition; + return newSelector; + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return 0; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return 0; + } + } + } + return max; // return number of matched selectors + }, + eval: function (env) { + var evaldCondition = this.condition && this.condition.eval(env); + + return this.createDerived(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + }), evaldCondition); + }, + genCSS: function (env, output) { + var i, element; + if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") { + output.add(' ', this.currentFileInfo, this.index); + } + if (!this._css) { + //TODO caching? speed comparison? + for(i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(env, output); + } + } + }, + toCSS: tree.toCSS, + markReferenced: function () { + this.isReferenced = true; + }, + getIsReferenced: function() { + return !this.currentFileInfo.reference || this.isReferenced; + }, + getIsOutput: function() { + return this.evaldCondition; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + eval: function () { return this; } +}; + +})(require('../tree')); + +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add("url("); + this.value.genCSS(env, output); + output.add(")"); + }, + toCSS: tree.toCSS, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + val.value = ctx.normalizePath(val.value); + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + genCSS: function (env, output) { + var i; + for(i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i+1 < this.value.length) { + output.add((env && env.compress) ? ',' : ', '); + } + } + }, + toCSS: tree.toCSS +}; + +})(require('../tree')); + +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { + this.name = name; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') === 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); + +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'rootpath', // option - rootpath to append to URL's + 'strictImports', // option - + 'insecure', // option - whether to allow imports from insecure ssl hosts + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true + 'mime', // browser only - mime type for sheet import + 'useFileCache', // browser only - whether to use the per file session cache + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' - absolute path to the entry file + // 'reference' - whether the file should not be output and only output parts that are referenced + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'cleancss', // whether to compress with clean-css + 'sourceMap', // whether to output a source map + 'importMultiple'// whether we are currently importing multiple copies + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + tree.evalEnv.prototype.normalizePath = function( path ) { + var + segments = path.split("/").reverse(), + segment; + + path = []; + while (segments.length !== 0 ) { + segment = segments.pop(); + switch( segment ) { + case ".": + break; + case "..": + if ((path.length === 0) || (path[path.length - 1] === "..")) { + path.push( segment ); + } else { + path.pop(); + } + break; + default: + path.push( segment ); + break; + } + } + + return path.join("/"); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + evald = this.flatten(evald); + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + }, + doAccept: function (node) { + node.accept(this); + }, + flatten: function(arr, master) { + return arr.reduce(this.flattenReduce.bind(this), master || []); + }, + flattenReduce: function(sum, element) { + if (element instanceof Array) { + sum = this.flatten(element, sum); + } else { + sum.push(element); + } + return sum; + } + }; + +})(require('./tree')); +(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode, + inlineCSS = importNode.options.inline; + + if (!importNode.css || inlineCSS) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + + if (importNode.options.multiple) { + env.importMultiple = true; + } + + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + + if (imported && !env.importMultiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + importNode.importedFilename = fullPath; + if (!inlineCSS && !importNode.skip) { + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + return; + } + } + + subFinish(); + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree')); +(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.selectors = rulesetNode.selectors.filter(function(selector) { return selector.getIsOutput(); }); + if (rulesetNode.selectors.length === 0) { + rulesetNode.rules.length = 0; + } + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree')); +(function (tree) { + tree.toCSSVisitor = function(env) { + this._visitor = new tree.visitor(this); + this._env = env; + }; + + tree.toCSSVisitor.prototype = { + isReplacing: true, + run: function (root) { + return this._visitor.visit(root); + }, + + visitRule: function (ruleNode, visitArgs) { + if (ruleNode.variable) { + return []; + } + return ruleNode; + }, + + visitMixinDefinition: function (mixinNode, visitArgs) { + return []; + }, + + visitExtend: function (extendNode, visitArgs) { + return []; + }, + + visitComment: function (commentNode, visitArgs) { + if (commentNode.isSilent(this._env)) { + return []; + } + return commentNode; + }, + + visitMedia: function(mediaNode, visitArgs) { + mediaNode.accept(this._visitor); + visitArgs.visitDeeper = false; + + if (!mediaNode.rules.length) { + return []; + } + return mediaNode; + }, + + visitDirective: function(directiveNode, visitArgs) { + if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) { + return []; + } + if (directiveNode.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (this.charset) { + if (directiveNode.debugInfo) { + var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n"); + comment.debugInfo = directiveNode.debugInfo; + return this._visitor.visit(comment); + } + return []; + } + this.charset = true; + } + return directiveNode; + }, + + checkPropertiesInRoot: function(rules) { + var ruleNode; + for(var i = 0; i < rules.length; i++) { + ruleNode = rules[i]; + if (ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null}; + } + } + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var rule, rulesets = []; + if (rulesetNode.firstRoot) { + this.checkPropertiesInRoot(rulesetNode.rules); + } + if (! rulesetNode.root) { + + rulesetNode.paths = rulesetNode.paths + .filter(function(p) { + var i; + if (p[0].elements[0].combinator.value === ' ') { + p[0].elements[0].combinator = new(tree.Combinator)(''); + } + for(i = 0; i < p.length; i++) { + if (p[i].getIsReferenced() && p[i].getIsOutput()) { + return true; + } + return false; + } + }); + + // Compile rules and rulesets + for (var i = 0; i < rulesetNode.rules.length; i++) { + rule = rulesetNode.rules[i]; + + if (rule.rules) { + // visit because we are moving them out from being a child + rulesets.push(this._visitor.visit(rule)); + rulesetNode.rules.splice(i, 1); + i--; + continue; + } + } + // accept the visitor to remove rules and refactor itself + // then we can decide now whether we want it or not + if (rulesetNode.rules.length > 0) { + rulesetNode.accept(this._visitor); + } + visitArgs.visitDeeper = false; + + this._mergeRules(rulesetNode.rules); + this._removeDuplicateRules(rulesetNode.rules); + + // now decide whether we keep the ruleset + if (rulesetNode.rules.length > 0 && rulesetNode.paths.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } else { + rulesetNode.accept(this._visitor); + visitArgs.visitDeeper = false; + if (rulesetNode.firstRoot || rulesetNode.rules.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } + if (rulesets.length === 1) { + return rulesets[0]; + } + return rulesets; + }, + + _removeDuplicateRules: function(rules) { + // remove duplicates + var ruleCache = {}, + ruleList, rule, i; + for(i = rules.length - 1; i >= 0 ; i--) { + rule = rules[i]; + if (rule instanceof tree.Rule) { + if (!ruleCache[rule.name]) { + ruleCache[rule.name] = rule; + } else { + ruleList = ruleCache[rule.name]; + if (ruleList instanceof tree.Rule) { + ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)]; + } + var ruleCSS = rule.toCSS(this._env); + if (ruleList.indexOf(ruleCSS) !== -1) { + rules.splice(i, 1); + } else { + ruleList.push(ruleCSS); + } + } + } + } + }, + + _mergeRules: function (rules) { + var groups = {}, + parts, + rule, + key; + + for (var i = 0; i < rules.length; i++) { + rule = rules[i]; + + if ((rule instanceof tree.Rule) && rule.merge) { + key = [rule.name, + rule.important ? "!" : ""].join(","); + + if (!groups[key]) { + parts = groups[key] = []; + } else { + rules.splice(i--, 1); + } + + parts.push(rule); + } + } + + Object.keys(groups).map(function (k) { + parts = groups[k]; + + if (parts.length > 1) { + rule = parts[0]; + + rule.value = new (tree.Value)(parts.map(function (p) { + return p.value; + })); + } + }); + } + }; + +})(require('./tree')); +(function (tree) { + /*jshint loopfunc:true */ + + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + rulesetNode.extendOnEveryPath = true; + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (rulesetNode.extendOnEveryPath || selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator === '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + elementValue1 = elementValue1.value; + elementValue2 = elementValue2.value; + if (elementValue1 instanceof tree.Selector) { + if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) { + return false; + } + for(var i = 0; i currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + newElements = selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)); + + if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) { + path[path.length - 1].elements = + path[path.length - 1].elements.concat(newElements); + } else { + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + newElements + )); + } + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.sourceMapOutput = function (options) { + this._css = []; + this._rootNode = options.rootNode; + this._writeSourceMap = options.writeSourceMap; + this._contentsMap = options.contentsMap; + this._sourceMapFilename = options.sourceMapFilename; + this._outputFilename = options.outputFilename; + this._sourceMapBasepath = options.sourceMapBasepath; + this._sourceMapRootpath = options.sourceMapRootpath; + this._outputSourceFiles = options.outputSourceFiles; + this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator; + + if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') { + this._sourceMapRootpath += '/'; + } + + this._lineNumber = 0; + this._column = 0; + }; + + tree.sourceMapOutput.prototype.normalizeFilename = function(filename) { + if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { + filename = filename.substring(this._sourceMapBasepath.length); + if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { + filename = filename.substring(1); + } + } + return (this._sourceMapRootpath || "") + filename.replace(/\\/g, '/'); + }; + + tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { + + //ignore adding empty strings + if (!chunk) { + return; + } + + var lines, + sourceLines, + columns, + sourceColumns, + i; + + if (fileInfo) { + var inputSource = this._contentsMap[fileInfo.filename].substring(0, index); + sourceLines = inputSource.split("\n"); + sourceColumns = sourceLines[sourceLines.length-1]; + } + + lines = chunk.split("\n"); + columns = lines[lines.length-1]; + + if (fileInfo) { + if (!mapLines) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column}, + original: { line: sourceLines.length, column: sourceColumns.length}, + source: this.normalizeFilename(fileInfo.filename)}); + } else { + for(i = 0; i < lines.length; i++) { + this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0}, + original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0}, + source: this.normalizeFilename(fileInfo.filename)}); + } + } + } + + if (lines.length === 1) { + this._column += columns.length; + } else { + this._lineNumber += lines.length - 1; + this._column = columns.length; + } + + this._css.push(chunk); + }; + + tree.sourceMapOutput.prototype.isEmpty = function() { + return this._css.length === 0; + }; + + tree.sourceMapOutput.prototype.toCSS = function(env) { + this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null }); + + if (this._outputSourceFiles) { + for(var filename in this._contentsMap) { + this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), this._contentsMap[filename]); + } + } + + this._rootNode.genCSS(env, this); + + if (this._css.length > 0) { + var sourceMapFilename, + sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON()); + + if (this._sourceMapFilename) { + sourceMapFilename = this.normalizeFilename(this._sourceMapFilename); + } + + if (this._writeSourceMap) { + this._writeSourceMap(sourceMapContent); + } else { + sourceMapFilename = "data:application/json," + encodeURIComponent(sourceMapContent); + } + + if (sourceMapFilename) { + this._css.push("/*# sourceMappingURL=" + sourceMapFilename + " */"); + } + } + + return this._css.join(''); + }; + +})(require('./tree')); + +// +// browser.js - client-side engine +// +/*global less, window, document, XMLHttpRequest, location */ + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + (location.port && + location.port.length > 0) || + isFileProtocol ? 'development' + : 'production'); + +var logLevel = { + info: 2, + errors: 1, + none: 0 +}; + +// The amount of logging in the javascript console. +// 2 - Information and errors +// 1 - Errors +// 0 - None +// Defaults to 2 +less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : logLevel.info; + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +var typePattern = /^text\/(x-)?less$/; +var cache = null; +var fileCache = {}; +var varsPre = ""; + +function log(str, level) { + if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) { + console.log('less: ' + str); + } +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function errorConsole(e, rootHref) { + var template = '{line} {content}'; + var filename = e.filename || rootHref; + var errors = []; + var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + " in " + filename + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + errors.join('\n'); + } else if (e.stack) { + content += e.stack; + } + log(content, logLevel.errors); +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss === null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + if (nextEl) { + nextEl.parentNode.insertBefore(css, nextEl); + } else { + head.appendChild(css); + } + } + if (oldCss && keepOldCss === false) { + oldCss.parentNode.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.', logLevel.info); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save', logLevel.errors); + } + } +} + +function errorHTML(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, errors = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] !== undefined) { + errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + errors.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} + +function error(e, rootHref) { + if (!less.errorReporting || less.errorReporting === "html") { + errorHTML(e, rootHref); + } else if (less.errorReporting === "console") { + errorConsole(e, rootHref); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("add", e, rootHref); + } +} + +function removeErrorHTML(path) { + var node = document.getElementById('less-error-message:' + extractId(path)); + if (node) { + node.parentNode.removeChild(node); + } +} + +function removeErrorConsole(path) { + //no action +} + +function removeError(path) { + if (!less.errorReporting || less.errorReporting === "html") { + removeErrorHTML(path); + } else if (less.errorReporting === "console") { + removeErrorConsole(path); + } else if (typeof less.errorReporting === 'function') { + less.errorReporting("remove", path); + } +} + +function loadStyles(newVars) { + var styles = document.getElementsByTagName('style'), + style; + for (var i = 0; i < styles.length; i++) { + style = styles[i]; + if (style.type.match(typePattern)) { + var env = new less.tree.parseEnv(less), + lessText = style.innerHTML || ''; + env.filename = document.location.href.replace(/#.*$/, ''); + + if (newVars || varsPre) { + env.useFileCache = true; + + lessText = varsPre + lessText; + + if (newVars) { + lessText += "\n" + newVars; + } + } + + /*jshint loopfunc:true */ + // use closure to store current value of i + var callback = (function(style) { + return function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }; + })(style); + new(less.Parser)(env).parse(lessText, callback); + } + } +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } else { + try { + /*global ActiveXObject */ + return new ActiveXObject("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX.", logLevel.errors); + return null; + } + } +} + +function doXHR(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + log("XHR: Getting '" + url + "'", logLevel.info); + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } +} + +function loadFile(originalHref, currentFileInfo, callback, env, newVars) { + + if (currentFileInfo && currentFileInfo.currentDirectory && !/^([a-z-]+:)?\//.test(originalHref)) { + originalHref = currentFileInfo.currentDirectory + originalHref; + } + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(originalHref, window.location.href); + var href = hrefParts.url; + var newFileInfo = { + currentDirectory: hrefParts.path, + filename: href + }; + + if (currentFileInfo) { + newFileInfo.entryPath = currentFileInfo.entryPath; + newFileInfo.rootpath = currentFileInfo.rootpath; + newFileInfo.rootFilename = currentFileInfo.rootFilename; + newFileInfo.relativeUrls = currentFileInfo.relativeUrls; + } else { + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + newFileInfo.relativeUrls = env.relativeUrls; + } + + if (newFileInfo.relativeUrls) { + if (env.rootpath) { + newFileInfo.rootpath = extractUrlParts(env.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + if (env.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + if (newVars) { + lessText += "\n" + newVars; + } + callback(null, lessText, href, newFileInfo, { lastModified: new Date() }); + } catch (e) { + callback(e, null, href); + } + return; + } + + doXHR(href, env.mime, function (data, lastModified) { + data = varsPre + data; + + // per file cache + fileCache[href] = data; + + // Use remote copy (re-parse) + try { + callback(null, data, href, newFileInfo, { lastModified: lastModified }); + } catch (e) { + callback(e, null, href); + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href); + }); +} + +function loadStyleSheet(sheet, callback, reload, remaining, newVars) { + + var env = new less.tree.parseEnv(less); + env.mime = sheet.type; + + if (newVars || varsPre) { + env.useFileCache = true; + } + + loadFile(sheet.href, null, function(e, data, path, newFileInfo, webInfo) { + + if (webInfo) { + webInfo.remaining = remaining; + + var css = cache && cache.getItem(path), + timestamp = cache && cache.getItem(path + ':timestamp'); + + if (!reload && timestamp && webInfo.lastModified && + (new(Date)(webInfo.lastModified).valueOf() === + new(Date)(timestamp).valueOf())) { + // Use local copy + createCSS(css, sheet); + webInfo.local = true; + callback(null, null, data, sheet, webInfo, path); + return; + } + } + + //TODO add tests around how this behaves when reloading + removeError(path); + + if (data) { + env.currentFileInfo = newFileInfo; + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, webInfo, path); + } catch (e) { + callback(e, null, null, sheet); + } + }); + } else { + callback(e, null, null, sheet, webInfo, path); + } + }, env, newVars); +} + +function loadStyleSheets(callback, reload, newVars) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), newVars); + } +} + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +function serializeVars(vars) { + var s = ""; + + for (var name in vars) { + s += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((vars[name].slice(-1) === ';')? vars[name] : vars[name] +';'); + } + + return s; +} + + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true; +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +less.modifyVars = function(record) { + less.refresh(false, serializeVars(record)); +}; + +less.refresh = function (reload, newVars) { + var startTime, endTime; + startTime = endTime = new Date(); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache.", logLevel.info); + } else { + log("parsed " + sheet.href + " successfully.", logLevel.info); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info); + if (env.remaining === 0) { + log("css generated in " + (new Date() - startTime) + 'ms', logLevel.info); + } + endTime = new Date(); + }, reload, newVars); + + loadStyles(newVars); +}; + +if (less.globalVars) { + varsPre = serializeVars(less.globalVars) + "\n"; +} + +less.refreshStyles = loadStyles; + +less.Parser.fileLoader = loadFile; + +less.refresh(less.env === 'development'); + +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} + +})(window); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.less new file mode 100644 index 000000000..7c60c0047 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.less @@ -0,0 +1,3 @@ +.a { + prop: (3 / #fff); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.txt b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.txt new file mode 100644 index 000000000..643bd593e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/console-errors/test-error.txt @@ -0,0 +1,2 @@ +less: OperationError: Can't substract or divide a color from a number in {pathhref}console-errors/test-error.less on line null, column 0: +1 prop: (3 / #fff); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/global-vars/simple.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/global-vars/simple.less new file mode 100644 index 000000000..00545b164 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/global-vars/simple.less @@ -0,0 +1,3 @@ +.test { + color: @global-var; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls.less new file mode 100644 index 000000000..290e6b412 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls.less @@ -0,0 +1,4 @@ +@import "modify-this.css"; +.modify { + my-url: url("a.png"); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls2.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls2.less new file mode 100644 index 000000000..b834bb9e1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/imports/urls2.less @@ -0,0 +1,4 @@ +@import "modify-again.css"; +.modify { + my-url: url("b.png"); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/imports/simple2.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/imports/simple2.less new file mode 100644 index 000000000..49fcf875f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/imports/simple2.less @@ -0,0 +1,4 @@ +@var2: blue; +.testisimported { + color: gainsboro; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/simple.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/simple.less new file mode 100644 index 000000000..64d993024 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/modify-vars/simple.less @@ -0,0 +1,6 @@ +@import "imports/simple2"; +@var1: red; +.test { + color1: @var1; + color2: @var2; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/relative-urls/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/relative-urls/urls.less new file mode 100644 index 000000000..b33fdfa60 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/relative-urls/urls.less @@ -0,0 +1,33 @@ +@import ".././imports/urls.less"; +@import "http://localhost:8081/test/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath-relative/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath-relative/urls.less new file mode 100644 index 000000000..1843fb224 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath-relative/urls.less @@ -0,0 +1,33 @@ +@import "../imports/urls.less"; +@import "http://localhost:8081/test/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath/urls.less new file mode 100644 index 000000000..1843fb224 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/rootpath/urls.less @@ -0,0 +1,33 @@ +@import "../imports/urls.less"; +@import "http://localhost:8081/test/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/urls.less new file mode 100644 index 000000000..596e5e7b8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/less/urls.less @@ -0,0 +1,57 @@ +@import "imports/urls.less"; +@import "http://localhost:8081/test/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} +#data-uri { + uri: data-uri('image/jpeg;base64', '../../data/image.jpg'); +} + +#data-uri-guess { + uri: data-uri('../../data/image.jpg'); +} + +#data-uri-ascii { + uri-1: data-uri('text/html', '../../data/page.html'); + uri-2: data-uri('../../data/page.html'); +} + +#data-uri-toobig { + uri: data-uri('../../data/data-uri-fail.png'); +} +#svg-functions { + background-image: svg-gradient(to bottom, black, white); + background-image: svg-gradient(to bottom, black, orange 3%, white); + @green_5: green 5%; + @orange_percentage: 3%; + @orange_color: orange; + background-image: svg-gradient(to bottom, (mix(black, white) + #444) 1%, @orange_color @orange_percentage, ((@green_5)), white 95%); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/phantom-runner.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/phantom-runner.js new file mode 100644 index 000000000..8233deb80 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/phantom-runner.js @@ -0,0 +1,150 @@ +var webpage = require('webpage'); +var server = require('webserver').create(); +var system = require('system'); +var fs = require('fs'); +var host; +var port = 8081; + +var listening = server.listen(port, function(request, response) { + //console.log("Requested " + request.url); + + var filename = ("test/" + request.url.slice(1)).replace(/[\\\/]/g, fs.separator); + + if (!fs.exists(filename) || !fs.isFile(filename)) { + response.statusCode = 404; + response.write("

    File Not Found

    File:" + filename + "

    "); + response.close(); + return; + } + + // we set the headers here + response.statusCode = 200; + response.headers = { + "Cache": "no-cache", + "Content-Type": "text/html" + }; + + response.write(fs.read(filename)); + + response.close(); +}); +if (!listening) { + console.log("could not create web server listening on port " + port); + phantom.exit(); +} + +/** + * Wait until the test condition is true or a timeout occurs. Useful for waiting + * on a server response or for a ui change (fadeIn, etc.) to occur. + * + * @param testFx javascript condition that evaluates to a boolean, + * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or + * as a callback function. + * @param onReady what to do when testFx condition is fulfilled, + * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or + * as a callback function. + * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. + * @param timeOutErrorMessage the error message if time out occurs + */ + +function waitFor(testFx, onReady, timeOutMillis, timeOutErrorMessage) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 10001, //< Default Max Timeout is 10s + start = new Date().getTime(), + condition = false, + interval = setInterval(function() { + if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code + } else { + if (!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + console.log(timeOutErrorMessage || "'waitFor()' timeout"); + phantom.exit(1); + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval); //< Stop this interval + } + } + }, 100); //< repeat check every 100ms +} + +function testPage(url) { + var page = webpage.create(); + page.open(url, function(status) { + if (status !== "success") { + console.log("Unable to access network - " + status); + phantom.exit(); + } else { + waitFor(function() { + return page.evaluate(function() { + return document.body && document.body.querySelector && + document.body.querySelector('.symbolSummary .pending') === null && + document.body.querySelector('.results') !== null; + }); + }, function() { + page.onConsoleMessage = function(msg) { + console.log(msg); + }; + var exitCode = page.evaluate(function() { + console.log(''); + console.log(document.body.querySelector('.description').innerText); + var list = document.body.querySelectorAll('.results > #details > .specDetail.failed'); + if (list && list.length > 0) { + console.log(''); + console.log(list.length + ' test(s) FAILED:'); + for (var i = 0; i < list.length; ++i) { + var el = list[i], + desc = el.querySelector('.description'), + msg = el.querySelector('.resultMessage.fail'); + console.log(''); + console.log(desc.innerText); + console.log(msg.innerText); + console.log(''); + } + return 1; + } else { + console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText); + return 0; + } + }); + testFinished(exitCode); + }, + 10000, // 10 second timeout + "Test failed waiting for jasmine results on page: " + url); + } + }); +} + +function scanDirectory(path, regex) { + var files = []; + fs.list(path).forEach(function(file) { + if (file.match(regex)) { + files.push(file); + } + }); + return files; +} + +var totalTests = 0, + totalFailed = 0, + totalDone = 0; + +function testFinished(failed) { + if (failed) { + totalFailed++; + } + totalDone++; + if (totalDone === totalTests) { + phantom.exit(totalFailed > 0 ? 1 : 0); + } +} + +if (system.args.length != 2 && system.args[1] != "--no-tests") { + var files = scanDirectory("test/browser/", /^test-runner-.+\.htm$/); + totalTests = files.length; + console.log("found " + files.length + " tests"); + files.forEach(function(file) { + testPage("http://localhost:8081/browser/" + file); + }); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-options.js new file mode 100644 index 000000000..3d73323e7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-options.js @@ -0,0 +1,42 @@ +var less = {}; + +// There originally run inside describe method. However, since they have not +// been inside it, they run at jasmine compile time (not runtime). It all +// worked cause less.js was in async mode and custom phantom runner had +// different setup then grunt-contrib-jasmine. They have been created before +// less.js run, even as they have been defined in spec. + +// test inline less in style tags by grabbing an assortment of less files and doing `@import`s +var testFiles = ['charsets', 'colors', 'comments', 'css-3', 'strings', 'media', 'mixins'], + testSheets = []; + +// setup style tags with less and link tags pointing to expected css output +for (var i = 0; i < testFiles.length; i++) { + var file = testFiles[i], + lessPath = '/test/less/' + file + '.less', + cssPath = '/test/css/' + file + '.css', + lessStyle = document.createElement('style'), + cssLink = document.createElement('link'), + lessText = '@import "' + lessPath + '";'; + + lessStyle.type = 'text/less'; + lessStyle.id = file; + lessStyle.href = file; + + if (lessStyle.styleSheet) { + lessStyle.styleSheet.cssText = lessText; + } else { + lessStyle.innerHTML = lessText; + } + + cssLink.rel = 'stylesheet'; + cssLink.type = 'text/css'; + cssLink.href = cssPath; + cssLink.id = 'expected-' + file; + + var head = document.getElementsByTagName('head')[0]; + + head.appendChild(lessStyle); + head.appendChild(cssLink); + testSheets[i] = lessStyle; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-spec.js new file mode 100644 index 000000000..ead27b4a0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-browser-spec.js @@ -0,0 +1,12 @@ +describe("less.js browser behaviour", function() { + testLessEqualsInDocument(); + + it("has some log messages", function() { + expect(logMessages.length).toBeGreaterThan(0); + }); + + for (var i = 0; i < testFiles.length; i++) { + var sheet = testSheets[i]; + testSheet(sheet); + } +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-console-errors.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-console-errors.js new file mode 100644 index 000000000..7af7bdb19 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-console-errors.js @@ -0,0 +1,5 @@ +less.errorReporting = 'console'; + +describe("less.js error reporting console test", function() { + testLessErrorsInDocument(true); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-options.js new file mode 100644 index 000000000..840ba5d63 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-options.js @@ -0,0 +1,5 @@ +var less = { + strictUnits: true, + strictMath: true +}; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-spec.js new file mode 100644 index 000000000..0b7206769 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-errors-spec.js @@ -0,0 +1,4 @@ +describe("less.js error tests", function() { + testLessErrorsInDocument(); +}); + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-options.js new file mode 100644 index 000000000..f313b2f77 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-options.js @@ -0,0 +1,4 @@ +var less = {}; +less.globalVars = { + "@global-var": "red" +}; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-spec.js new file mode 100644 index 000000000..6dba89170 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-global-vars-spec.js @@ -0,0 +1,3 @@ +describe("less.js global vars", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-options.js new file mode 100644 index 000000000..9e4b95921 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-options.js @@ -0,0 +1,4 @@ +var less = {}; +less.strictMath = false; +less.strictUnits = false; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-spec.js new file mode 100644 index 000000000..6ba7bfae7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-legacy-spec.js @@ -0,0 +1,3 @@ +describe("less.js legacy tests", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-options.js new file mode 100644 index 000000000..df51782a8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-options.js @@ -0,0 +1,15 @@ +var less = {}; +less.strictMath = true; +less.functions = { + add: function(a, b) { + return new(less.tree.Dimension)(a.value + b.value); + }, + increment: function(a) { + return new(less.tree.Dimension)(a.value + 1); + }, + _color: function(str) { + if (str.value === "evil red") { + return new(less.tree.Color)("600"); + } + } +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-spec.js new file mode 100644 index 000000000..b5261e754 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-main-spec.js @@ -0,0 +1,3 @@ +describe("less.js main tests", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-options.js new file mode 100644 index 000000000..2799ad55d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-options.js @@ -0,0 +1,2 @@ +/* exported less */ +var less = {}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-spec.js new file mode 100644 index 000000000..25ea5b68a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-modify-vars-spec.js @@ -0,0 +1,42 @@ +var alreadyRun = false; + +describe("less.js modify vars", function() { + beforeEach(function() { + // simulating "setUp" or "beforeAll" method + var lessOutputObj; + if (alreadyRun) + return; + + alreadyRun = true; + + // wait until the sheet is compiled first time + waitsFor(function() { + lessOutputObj = document.getElementById("less:test-less-simple"); + return lessOutputObj !== null; + }, "first generation of less:test-less-simple", 7000); + + // modify variables + runs(function() { + lessOutputObj.type = "not compiled yet"; + less.modifyVars({ + var1: "green", + var2: "purple" + }); + }); + + // wait until variables are modified + waitsFor(function() { + lessOutputObj = document.getElementById("less:test-less-simple"); + return lessOutputObj !== null && lessOutputObj.type === "text/css"; + }, "second generation of less:test-less-simple", 7000); + + }); + + testLessEqualsInDocument(); + it("Should log only 2 XHR requests", function() { + var xhrLogMessages = logMessages.filter(function(item) { + return (/XHR: Getting '/).test(item); + }); + expect(xhrLogMessages.length).toEqual(2); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-options.js new file mode 100644 index 000000000..2a4649447 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-options.js @@ -0,0 +1,4 @@ +var less = {}; + +less.strictUnits = true; +less.javascriptEnabled = false; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-spec.js new file mode 100644 index 000000000..38aefe292 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-no-js-errors-spec.js @@ -0,0 +1,4 @@ +describe("less.js javascript disabled error tests", function() { + testLessErrorsInDocument(); +}); + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-options.js new file mode 100644 index 000000000..f8189d6a8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-options.js @@ -0,0 +1,3 @@ +var less = {}; +less.env = "production"; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-spec.js new file mode 100644 index 000000000..8c8d8f42f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-production-spec.js @@ -0,0 +1,5 @@ +describe("less.js production behaviour", function() { + it("doesn't log any messages", function() { + expect(logMessages.length).toEqual(0); + }); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-options.js new file mode 100644 index 000000000..a20eb591e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-options.js @@ -0,0 +1,3 @@ +var less = {}; +less.relativeUrls = true; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-spec.js new file mode 100644 index 000000000..b13911ee8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-relative-urls-spec.js @@ -0,0 +1,3 @@ +describe("less.js browser test - relative url's", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-options.js new file mode 100644 index 000000000..5e475bb40 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-options.js @@ -0,0 +1,3 @@ +var less = {}; +less.rootpath = "https://www.github.com/"; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-options.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-options.js new file mode 100644 index 000000000..f97baa4b8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-options.js @@ -0,0 +1,4 @@ +var less = {}; +less.rootpath = "https://www.github.com/cloudhead/less.js/"; +less.relativeUrls = true; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-spec.js new file mode 100644 index 000000000..cd905739a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-relative-spec.js @@ -0,0 +1,3 @@ +describe("less.js browser test - rootpath and relative url's", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-spec.js b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-spec.js new file mode 100644 index 000000000..b7b9ba1d6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/runner-rootpath-spec.js @@ -0,0 +1,3 @@ +describe("less.js browser test - rootpath url's", function() { + testLessEqualsInDocument(); +}); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/browser/test-runner-template.tmpl b/node_modules/grunt-contrib-less/node_modules/less/test/browser/test-runner-template.tmpl new file mode 100644 index 000000000..17f644f5f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/browser/test-runner-template.tmpl @@ -0,0 +1,47 @@ + + + + + Jasmine Spec Runner + + + <% var generateScriptTags = function(allScripts) { allScripts.forEach(function(script){ %> + + <% }); }; %> + + + <% scripts.src.forEach(function(fullLessName) { + var pathParts = fullLessName.split('/'); + var fullCssName = fullLessName.replace(/less/g, 'css'); + var lessName = pathParts[pathParts.length - 1]; + var name = lessName.split('.')[0]; %> + + + + <% }); %> + + + <% css.forEach(function(style){ %> + + <% }) %> + + + <% generateScriptTags([].concat(scripts.polyfills, scripts.jasmine)); %> + + + <% generateScriptTags(scripts.helpers); %> + + + <% generateScriptTags(scripts.vendor); %> + + + <% generateScriptTags(scripts.specs); %> + + + <% generateScriptTags([].concat(scripts.reporters, scripts.start)); %> + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/charsets.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/charsets.css new file mode 100644 index 000000000..9f44090c9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/charsets.css @@ -0,0 +1 @@ +@charset "UTF-8"; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/colors.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/colors.css new file mode 100644 index 000000000..169567726 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/colors.css @@ -0,0 +1,80 @@ +#yelow #short { + color: #fea; +} +#yelow #long { + color: #ffeeaa; +} +#yelow #rgba { + color: rgba(255, 238, 170, 0.1); +} +#yelow #argb { + color: #1affeeaa; +} +#blue #short { + color: #00f; +} +#blue #long { + color: #0000ff; +} +#blue #rgba { + color: rgba(0, 0, 255, 0.1); +} +#blue #argb { + color: #1a0000ff; +} +#alpha #hsla { + color: rgba(61, 45, 41, 0.6); +} +#overflow .a { + color: #000000; +} +#overflow .b { + color: #ffffff; +} +#overflow .c { + color: #ffffff; +} +#overflow .d { + color: #00ff00; +} +#grey { + color: #c8c8c8; +} +#333333 { + color: #333333; +} +#808080 { + color: #808080; +} +#00ff00 { + color: #00ff00; +} +.lightenblue { + color: #3333ff; +} +.darkenblue { + color: #0000cc; +} +.unknowncolors { + color: blue2; + border: 2px solid superred; +} +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha #fromvar { + opacity: 0.7; +} +#alpha #short { + opacity: 1; +} +#alpha #long { + opacity: 1; +} +#alpha #rgba { + opacity: 0.2; +} +#alpha #hsl { + opacity: 1; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/comments.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/comments.css new file mode 100644 index 000000000..b85f5b4f1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/comments.css @@ -0,0 +1,69 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ +/* + + Comment + +*/ +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ +/* @group Variables +------------------- */ +#comments, +.comments { + /**/ + color: red; + /* A C-style comment */ + /* A C-style comment */ + background-color: orange; + font-size: 12px; + /* lost comment */ + content: "content"; + border: 1px solid black; + padding: 0; + margin: 2em; +} +/* commented out + #more-comments { + color: grey; + } +*/ +.selector, +.lots, +.comments { + color: #808080, /* blue */ #ffa500; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: 8px /* moz only with operation */; +} +.test { + color: 1px; +} +#last { + color: #0000ff; +} +/* */ +/* { */ +/* */ +/* */ +/* */ +#div { + color: #A33; +} +/* } */ diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/compression/compression.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/compression/compression.css new file mode 100644 index 000000000..8d6786e58 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/compression/compression.css @@ -0,0 +1,3 @@ +#colours{color1:#fea;color2:#fea;color3:rgba(255,238,170,0.1);string:"#ffeeaa";/*! but not this type + Note preserved whitespace + */}dimensions{val:.1px;val:0;val:4cm;val:.2;val:5;angles-must-have-unit:0deg;durations-must-have-unit:0s;length-doesnt-have-unit:0;width:auto\9}@page{marks:none;@top-left-corner{vertical-align:top}@top-left{vertical-align:top}} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/css-3.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-3.css new file mode 100644 index 000000000..93b0a001a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-3.css @@ -0,0 +1,125 @@ +.comma-delimited { + text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; + -webkit-transform: rotate(-0.0000000001deg); +} +@font-face { + font-family: Headline; + unicode-range: U+??????, U+0???, U+0-7F, U+A5; +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} +div#id.class[a=1][b=2].class:not(1) { + color: white; +} +ul.comma > li:not(:only-child)::after { + color: white; +} +ol.comma > li:nth-last-child(2)::after { + color: white; +} +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} +a[href^="http://"] { + color: black; +} +a[href$="http://"] { + color: black; +} +form[data-disabled] { + color: black; +} +p::before { + color: black; +} +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} +@-webkit-keyframes frames { + 0% { + border: 1px; + } + 5.5% { + border: 2px; + } + 100% { + border: 3px; + } +} +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from, + to { + font-size: 12px; + } + 0%, + 100% { + font-size: 12px; + } +} +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} +@viewport { + font-size: 10px; +} +@namespace foo url(http://www.example.com); +foo|h1 { + color: blue; +} +foo|* { + color: yellow; +} +|h1 { + color: red; +} +*|h1 { + color: green; +} +h1 { + color: green; +} +.upper-test { + UpperCaseProperties: allowed; +} +@host { + div { + display: block; + } +} +::distributed(input::placeholder) { + color: #b3b3b3; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/css-escapes.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-escapes.css new file mode 100644 index 000000000..4d343aa62 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-escapes.css @@ -0,0 +1,24 @@ +.escape\|random\|char { + color: red; +} +.mixin\!tUp { + font-weight: bold; +} +.\34 04 { + background: red; +} +.\34 04 strong { + color: #ff00ff; + font-weight: bold; +} +.trailingTest\+ { + color: red; +} +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/css-guards.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-guards.css new file mode 100644 index 000000000..dbb27dae3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/css-guards.css @@ -0,0 +1,18 @@ +.light { + color: green; +} +.see-the { + color: orange; +} +.hide-the { + color: green; +} +.multiple-conditions-1 { + color: red; +} +.inheritance .test { + color: black; +} +.inheritance:hover { + color: pink; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/css.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/css.css new file mode 100644 index 000000000..b011a7e38 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/css.css @@ -0,0 +1,95 @@ +@charset "utf-8"; +div { + color: black; +} +div { + width: 99%; +} +* { + min-width: 45em; +} +h1, +h2 > a > p, +h3 { + color: none; +} +div.class { + color: blue; +} +div#id { + color: green; +} +.class#id { + color: purple; +} +.one.two.three { + color: grey; +} +@media print { + * { + font-size: 3em; + } +} +@media screen { + * { + font-size: 10px; + } +} +@font-face { + font-family: 'Garamond Pro'; +} +a:hover, +a:link { + color: #999; +} +p, +p:first-child { + text-transform: none; +} +q:lang(no) { + quotes: none; +} +p + h1 { + font-size: 2.2em; +} +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; +} +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small / 20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; + border-radius: 5px / 10px; +} +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff)); + margin: ; + filter: alpha(opacity=100); + width: auto\9; +} +.misc .nested-multiple { + multiple-semi-colons: yes; +} +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} +@font-face { + font-family: font-a; +} +@font-face { + font-family: font-b; +} +.æøå { + margin: 0; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-all.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-all.css new file mode 100644 index 000000000..c6fb355b3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-all.css @@ -0,0 +1,43 @@ +@charset "UTF-8"; +/* line 3, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}} +/* @charset "ISO-8859-1"; */ +/* line 23, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}} +.tst3 { + color: grey; +} +/* line 15, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000315}} +.test1 { + color: black; +} +/* line 6, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\000036}} +.test2 { + color: red; +} +@media all { + /* line 5, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000035}} + .tst { + color: black; + } +} +@media all and screen { + /* line 7, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000037}} + .tst { + color: red; + } + /* line 9, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000039}} + .tst .tst3 { + color: white; + } +} +/* line 18, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000318}} +.tst2 { + color: white; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-comments.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-comments.css new file mode 100644 index 000000000..9c48baa96 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-comments.css @@ -0,0 +1,35 @@ +@charset "UTF-8"; +/* line 3, {pathimport}test.less */ +/* @charset "ISO-8859-1"; */ +/* line 23, {pathimport}test.less */ +.tst3 { + color: grey; +} +/* line 15, {path}linenumbers.less */ +.test1 { + color: black; +} +/* line 6, {path}linenumbers.less */ +.test2 { + color: red; +} +@media all { + /* line 5, {pathimport}test.less */ + .tst { + color: black; + } +} +@media all and screen { + /* line 7, {pathimport}test.less */ + .tst { + color: red; + } + /* line 9, {pathimport}test.less */ + .tst .tst3 { + color: white; + } +} +/* line 18, {pathimport}test.less */ +.tst2 { + color: white; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-mediaquery.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-mediaquery.css new file mode 100644 index 000000000..3fdbbafcb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/debug/linenumbers-mediaquery.css @@ -0,0 +1,35 @@ +@charset "UTF-8"; +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}} +/* @charset "ISO-8859-1"; */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}} +.tst3 { + color: grey; +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000315}} +.test1 { + color: black; +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\000036}} +.test2 { + color: red; +} +@media all { + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000035}} + .tst { + color: black; + } +} +@media all and screen { + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000037}} + .tst { + color: red; + } + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000039}} + .tst .tst3 { + color: white; + } +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000318}} +.tst2 { + color: white; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-chaining.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-chaining.css new file mode 100644 index 000000000..820e134f0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-chaining.css @@ -0,0 +1,81 @@ +.a, +.b, +.c { + color: black; +} +.f, +.e, +.d { + color: black; +} +.g.h, +.i.j.h, +.k.j.h { + color: black; +} +.i.j, +.k.j { + color: white; +} +.l, +.m, +.n, +.o, +.p, +.q, +.r, +.s, +.t { + color: black; +} +.u, +.v.u.v { + color: black; +} +.w, +.v.w.v { + color: black; +} +.x, +.y, +.z { + color: x; +} +.y, +.z, +.x { + color: y; +} +.z, +.x, +.y { + color: z; +} +.va, +.vb, +.vc { + color: black; +} +.vb, +.vc { + color: white; +} +@media tv { + .ma, + .mb, + .mc { + color: black; + } + .md, + .ma, + .mb, + .mc { + color: white; + } +} +@media tv and plasma { + .me, + .mf { + background: red; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-clearfix.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-clearfix.css new file mode 100644 index 000000000..966892a27 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-clearfix.css @@ -0,0 +1,19 @@ +.clearfix, +.foo, +.bar { + *zoom: 1; +} +.clearfix:after, +.foo:after, +.bar:after { + content: ''; + display: block; + clear: both; + height: 0; +} +.foo { + color: red; +} +.bar { + color: blue; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-exact.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-exact.css new file mode 100644 index 000000000..beff4133e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-exact.css @@ -0,0 +1,37 @@ +.replace.replace .replace, +.c.replace + .replace .replace, +.replace.replace .c, +.c.replace + .replace .c, +.rep_ace { + prop: copy-paste-replace; +} +.a .b .c { + prop: not_effected; +} +.a, +.effected { + prop: is_effected; +} +.a .b { + prop: not_effected; +} +.a .b.c { + prop: not_effected; +} +.c .b .a, +.a .b .a, +.c .a .a, +.a .a .a, +.c .b .c, +.a .b .c, +.c .a .c, +.a .a .c { + prop: not_effected; +} +.e.e, +.dbl { + prop: extend-double; +} +.e.e:hover { + hover: not-extended; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-media.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-media.css new file mode 100644 index 000000000..23bd7b85c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-media.css @@ -0,0 +1,24 @@ +.ext1 .ext2, +.all .ext2 { + background: black; +} +@media tv { + .ext1 .ext3, + .tv-lowres .ext3, + .all .ext3 { + color: white; + } + .tv-lowres { + background: blue; + } +} +@media tv and hires { + .ext1 .ext4, + .tv-hires .ext4, + .all .ext4 { + color: green; + } + .tv-hires { + background: red; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-nest.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-nest.css new file mode 100644 index 000000000..2c3905d95 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-nest.css @@ -0,0 +1,57 @@ +.sidebar, +.sidebar2, +.type1 .sidebar3, +.type2.sidebar4 { + width: 300px; + background: red; +} +.sidebar .box, +.sidebar2 .box, +.type1 .sidebar3 .box, +.type2.sidebar4 .box { + background: #FFF; + border: 1px solid #000; + margin: 10px 0; +} +.sidebar2 { + background: blue; +} +.type1 .sidebar3 { + background: green; +} +.type2.sidebar4 { + background: red; +} +.button, +.submit { + color: black; +} +.button:hover, +.submit:hover { + color: white; +} +.button2 :hover { + nested: white; +} +.button2 :hover { + notnested: black; +} +.amp-test-h, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g { + test: extended by masses of selectors; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-selector.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-selector.css new file mode 100644 index 000000000..da47254b3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend-selector.css @@ -0,0 +1,80 @@ +.error, +.badError { + border: 1px #f00; + background: #fdd; +} +.error.intrusion, +.badError.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error, +.intrusion .badError { + display: none; +} +.badError { + border-width: 3px; +} +.foo .bar, +.foo .baz, +.ext1 .ext2 .bar, +.ext1 .ext2 .baz, +.ext3 .bar, +.ext3 .baz, +.ext4 .bar, +.ext4 .baz { + display: none; +} +div.ext5, +.ext6 > .ext5, +div.ext7, +.ext6 > .ext7 { + width: 100px; +} +.ext, +.a .c, +.b .c { + test: 1; +} +.a, +.b { + test: 2; +} +.a .c, +.b .c { + test: 3; +} +.a .c .d, +.b .c .d { + test: 4; +} +.replace.replace .replace, +.c.replace + .replace .replace, +.replace.replace .c, +.c.replace + .replace .c, +.rep_ace.rep_ace .rep_ace, +.c.rep_ace + .rep_ace .rep_ace, +.rep_ace.rep_ace .c, +.c.rep_ace + .rep_ace .c { + prop: copy-paste-replace; +} +.attributes [data="test"], +.attributes .attributes .attribute-test { + extend: attributes; +} +.attributes [data], +.attributes .attributes .attribute-test2 { + extend: attributes2; +} +.attributes [data="test3"], +.attributes .attributes .attribute-test { + extend: attributes2; +} +.header .header-nav, +.footer .footer-nav { + background: red; +} +.header .header-nav:before, +.footer .footer-nav:before { + background: blue; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extend.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend.css new file mode 100644 index 000000000..2895641a7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extend.css @@ -0,0 +1,76 @@ +.error, +.badError { + border: 1px #f00; + background: #fdd; +} +.error.intrusion, +.badError.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error, +.intrusion .badError { + display: none; +} +.badError { + border-width: 3px; +} +.foo .bar, +.foo .baz, +.ext1 .ext2 .bar, +.ext1 .ext2 .baz, +.ext3 .bar, +.ext3 .baz, +.foo .ext3, +.ext4 .bar, +.ext4 .baz, +.foo .ext4 { + display: none; +} +div.ext5, +.ext6 > .ext5, +div.ext7, +.ext6 > .ext7 { + width: 100px; +} +.ext8.ext9, +.fuu { + result: add-foo; +} +.ext8 .ext9, +.ext8 + .ext9, +.ext8 > .ext9, +.buu, +.zap, +.zoo { + result: bar-matched; +} +.ext8.nomatch { + result: none; +} +.ext8 .ext9, +.buu { + result: match-nested-bar; +} +.ext8.ext9, +.fuu { + result: match-nested-foo; +} +.aa, +.cc { + color: black; +} +.aa .dd, +.aa .ee { + background: red; +} +.bb, +.cc, +.ee, +.ff { + background: red; +} +.bb .bb, +.ff .ff { + color: black; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/extract-and-length.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/extract-and-length.css new file mode 100644 index 000000000..f550e201b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/extract-and-length.css @@ -0,0 +1,133 @@ +.multiunit { + length: 6; + extract: abc "abc" 1 1px 1% #112233; +} +.incorrect-index { + v1: extract(a b c, 5); + v2: extract(a, b, c, -2); +} +.scalar { + var-value: variable; + var-length: 1; + ill-index: extract(variable, 2); + name-value: name; + string-value: "string"; + number-value: 12345678; + color-value: #0000ff; + rgba-value: rgba(80, 160, 240, 0.67); + empty-value: ; + name-length: 1; + string-length: 1; + number-length: 1; + color-length: 1; + rgba-length: 1; + empty-length: 1; +} +.mixin-arguments-1 { + length: 4; + extract: c | b | a; +} +.mixin-arguments-2 { + length: 4; + extract: c | b | a; +} +.mixin-arguments-3 { + length: 4; + extract: c | b | a; +} +.mixin-arguments-4 { + length: 0; + extract: extract(, 2) | extract(, 1); +} +.mixin-arguments-2 { + length: 4; + extract: c | b | a; +} +.mixin-arguments-3 { + length: 4; + extract: c | b | a; +} +.mixin-arguments-4 { + length: 3; + extract: c | b; +} +.mixin-arguments-2 { + length: 4; + extract: 3 | 2 | 1; +} +.mixin-arguments-3 { + length: 4; + extract: 3 | 2 | 1; +} +.mixin-arguments-4 { + length: 3; + extract: 3 | 2; +} +.md-space-comma { + length-1: 3; + extract-1: 1 2 3; + length-2: 3; + extract-2: 2; +} +.md-space-comma-as-args-2 { + length: 3; + extract: "x" "y" "z" | 1 2 3 | a b c; +} +.md-space-comma-as-args-3 { + length: 3; + extract: "x" "y" "z" | 1 2 3 | a b c; +} +.md-space-comma-as-args-4 { + length: 2; + extract: "x" "y" "z" | 1 2 3; +} +.md-cat-space-comma { + length-1: 3; + extract-1: 1 2 3; + length-2: 3; + extract-2: 2; +} +.md-cat-space-comma-as-args-2 { + length: 3; + extract: "x" "y" "z" | 1 2 3 | a b c; +} +.md-cat-space-comma-as-args-3 { + length: 3; + extract: "x" "y" "z" | 1 2 3 | a b c; +} +.md-cat-space-comma-as-args-4 { + length: 2; + extract: "x" "y" "z" | 1 2 3; +} +.md-cat-comma-space { + length-1: 3; + extract-1: 1, 2, 3; + length-2: 3; + extract-2: 2; +} +.md-cat-comma-space-as-args-1 { + length: 3; + extract: "x", "y", "z" | 1, 2, 3 | a, b, c; +} +.md-cat-comma-space-as-args-2 { + length: 3; + extract: "x", "y", "z" | 1, 2, 3 | a, b, c; +} +.md-cat-comma-space-as-args-3 { + length: 3; + extract: "x", "y", "z" | 1, 2, 3 | a, b, c; +} +.md-cat-comma-space-as-args-4 { + length: 0; + extract: extract(, 2) | extract(, 1); +} +.md-3D { + length-1: 2; + extract-1: a b c d, 1 2 3 4; + length-2: 2; + extract-2: 5 6 7 8; + length-3: 4; + extract-3: 7; + length-4: 1; + extract-4: 8; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/functions.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/functions.css new file mode 100644 index 000000000..9694a7a3b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/functions.css @@ -0,0 +1,139 @@ +#functions { + color: #660000; + width: 16; + height: undefined("self"); + border-width: 5; + variable: 11; + background: linear-gradient(#000000, #ffffff); +} +#built-in { + escaped: -Some::weird(#thing, y); + lighten: #ffcccc; + darken: #330000; + saturate: #203c31; + desaturate: #29332f; + greyscale: #2e2e2e; + hsl-clamp: #ffffff; + spin-p: #bf6a40; + spin-n: #bf4055; + luma-white: 100%; + luma-black: 0%; + luma-black-alpha: 0%; + luma-red: 21%; + luma-green: 72%; + luma-blue: 7%; + luma-yellow: 93%; + luma-cyan: 79%; + luma-white-alpha: 50%; + contrast-filter: contrast(30%); + saturate-filter: saturate(5%); + contrast-white: #000000; + contrast-black: #ffffff; + contrast-red: #ffffff; + contrast-green: #000000; + contrast-blue: #ffffff; + contrast-yellow: #000000; + contrast-cyan: #000000; + contrast-light: #111111; + contrast-dark: #eeeeee; + contrast-wrongorder: #111111; + contrast-light-thresh: #111111; + contrast-dark-thresh: #eeeeee; + contrast-high-thresh: #eeeeee; + contrast-low-thresh: #111111; + contrast-light-thresh-per: #111111; + contrast-dark-thresh-per: #eeeeee; + contrast-high-thresh-per: #eeeeee; + contrast-low-thresh-per: #111111; + format: "rgb(32, 128, 64)"; + format-string: "hello world"; + format-multiple: "hello earth 2"; + format-url-encode: "red is %23ff0000"; + eformat: rgb(32, 128, 64); + unitless: 12; + unit: 14em; + hue: 98; + saturation: 12%; + lightness: 95%; + hsvhue: 98; + hsvsaturation: 12%; + hsvvalue: 95%; + red: 255; + green: 255; + blue: 255; + rounded: 11; + rounded-two: 10.67; + roundedpx: 3px; + roundedpx-three: 3.333px; + rounded-percentage: 10%; + ceil: 11px; + floor: 12px; + sqrt: 5px; + pi: 3.141592653589793; + mod: 2m; + abs: 4%; + tan: 0.9004040442978399; + sin: 0.17364817766693033; + cos: 0.8438539587324921; + atan: 0.1rad; + atan: 34.00000000000001deg; + atan: 45.00000000000001deg; + pow: 64px; + pow: 64; + pow: 27; + min: 0; + min: min("junk", 5); + min: 3pt; + max: 3; + max: max(8%, 1cm); + percentage: 20%; + color: #ff0011; + tint: #898989; + tint-full: #ffffff; + tint-percent: #898989; + shade: #686868; + shade-full: #000000; + shade-percent: #686868; + fade-out: rgba(255, 0, 0, 0.95); + fade-in: rgba(255, 0, 0, 0.9500000000000001); + hsv: #4d2926; + hsva: rgba(77, 40, 38, 0.2); + mix: #ff3300; + mix-0: #ffff00; + mix-100: #ff0000; + mix-weightless: #ff8000; + mixt: rgba(255, 0, 0, 0.5); +} +#built-in .is-a { + color: true; + color1: true; + color2: true; + color3: true; + keyword: true; + number: true; + string: true; + pixel: true; + percent: true; + em: true; + cat: true; +} +#alpha { + alpha: rgba(153, 94, 51, 0.6); + alpha2: 0.5; + alpha3: 0; +} +#blendmodes { + multiply: #ed0000; + screen: #f600f6; + overlay: #ed0000; + softlight: #ff0000; + hardlight: #0000ed; + difference: #f600f6; + exclusion: #f600f6; + average: #7b007b; + negation: #d73131; +} +#extract-and-length { + extract: 3 2 1 C B A; + length: 6; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/ie-filters.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/ie-filters.css new file mode 100644 index 000000000..007aa536b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/ie-filters.css @@ -0,0 +1,9 @@ +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0); +} +.evalTest1 { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=5); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/import-inline.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-inline.css new file mode 100644 index 000000000..f198d3c16 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-inline.css @@ -0,0 +1,5 @@ +this isn't very valid CSS. +@media (min-width: 600px) { + #css { color: yellow; } + +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/import-interpolation.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-interpolation.css new file mode 100644 index 000000000..16b7a1502 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-interpolation.css @@ -0,0 +1,6 @@ +body { + width: 100%; +} +.a { + var: test; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/import-once.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-once.css new file mode 100644 index 000000000..2f86b3b34 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-once.css @@ -0,0 +1,15 @@ +#import { + color: #ff0000; +} +body { + width: 100%; +} +.test-f { + height: 10px; +} +body { + width: 100%; +} +.test-f { + height: 10px; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/import-reference.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-reference.css new file mode 100644 index 000000000..c2d055a79 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/import-reference.css @@ -0,0 +1,55 @@ +/* + The media statement above is invalid (no selector) + We should ban invalid media queries with properties and no selector? +*/ +.visible { + color: red; +} +.visible .c { + color: green; +} +.visible { + color: green; +} +.visible:hover { + color: green; +} +.visible { + color: green; +} +.only-with-visible + .visible, +.visible + .only-with-visible, +.visible + .visible { + color: green; +} +.only-with-visible + .visible .sub, +.visible + .only-with-visible .sub, +.visible + .visible .sub { + color: green; +} +.b { + color: red; + color: green; +} +.b .c { + color: green; +} +.b:hover { + color: green; +} +.b { + color: green; +} +.b + .b { + color: green; +} +.b + .b .sub { + color: green; +} +.y { + pulled-in: yes; +} +/* comment pulled in */ +.visible { + extend: test; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/import.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/import.css new file mode 100644 index 000000000..a37491813 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/import.css @@ -0,0 +1,36 @@ +@import url(http://fonts.googleapis.com/css?family=Open+Sans); +@import url(/absolute/something.css) screen and (color) and (max-width: 600px); +@import url("//ha.com/file.css") (min-width: 100px); +#import-test { + height: 10px; + color: #ff0000; + width: 10px; + height: 30%; +} +@media screen and (max-width: 600px) { + body { + width: 100%; + } +} +#import { + color: #ff0000; +} +.mixin { + height: 10px; + color: #ff0000; +} +@media screen and (max-width: 601px) { + #css { + color: yellow; + } +} +@media screen and (max-width: 602px) { + body { + width: 100%; + } +} +@media screen and (max-width: 603px) { + #css { + color: yellow; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/javascript.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/javascript.css new file mode 100644 index 000000000..8268ab333 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/javascript.css @@ -0,0 +1,23 @@ +.eval { + js: 42; + js: 2; + js: "hello world"; + js: 1, 2, 3; + title: "string"; + ternary: true; + multiline: 2; +} +.scope { + var: 42; + escaped: 7px; +} +.vars { + width: 8; +} +.escape-interpol { + width: hello world; +} +.arrays { + ary: "1, 2, 3"; + ary1: "1, 2, 3"; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/lazy-eval.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/lazy-eval.css new file mode 100644 index 000000000..1adfb8f38 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/lazy-eval.css @@ -0,0 +1,3 @@ +.lazy-eval { + width: 100%; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/legacy/legacy.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/legacy/legacy.css new file mode 100644 index 000000000..2f9bb80b5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/legacy/legacy.css @@ -0,0 +1,7 @@ +@media (-o-min-device-pixel-ratio: 2/1) { + .test-math-and-units { + font: ignores 0/0 rules; + test-division: 7em; + simple: 2px; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/media.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/media.css new file mode 100644 index 000000000..607f0e44e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/media.css @@ -0,0 +1,219 @@ +@media print { + .class { + color: blue; + } + .class .sub { + width: 42; + } + .top, + header > h1 { + color: #444444; + } +} +@media screen { + body { + max-width: 480; + } +} +@media all and (device-aspect-ratio: 16 / 9) { + body { + max-width: 800px; + } +} +@media all and (orientation: portrait) { + aside { + float: none; + } +} +@media handheld and (min-width: 42), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} +@media print { + body { + padding: 20px; + } + body header { + background-color: red; + } +} +@media print and (orientation: landscape) { + body { + margin-left: 20px; + } +} +@media screen { + .sidebar { + width: 300px; + } +} +@media screen and (orientation: landscape) { + .sidebar { + width: 500px; + } +} +@media a and b { + .first .second .third { + width: 300px; + } + .first .second .fourth { + width: 3; + } +} +@media a and b and c { + .first .second .third { + width: 500px; + } +} +@media a, b and c { + body { + width: 95%; + } +} +@media a and x, b and c and x, a and y, b and c and y { + body { + width: 100%; + } +} +.a { + background: black; +} +@media handheld { + .a { + background: white; + } +} +@media handheld and (max-width: 100px) { + .a { + background: red; + } +} +.b { + background: black; +} +@media handheld { + .b { + background: white; + } +} +@media handheld and (max-width: 200px) { + .b { + background: red; + } +} +@media only screen and (max-width: 200px) { + body { + width: 480px; + } +} +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in; + + @top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} +body { + background: red; +} +@media (max-width: 500px) { + body { + background: green; + } +} +@media (max-width: 1000px) { + body { + background: red; + background: blue; + } +} +@media (max-width: 1000px) and (max-width: 500px) { + body { + background: green; + } +} +@media (max-width: 1200px) { + /* a comment */ +} +@media (max-width: 1200px) and (max-width: 900px) { + body { + font-size: 11px; + } +} +@media (min-width: 480px) { + .nav-justified > li { + display: table-cell; + } +} +@media (min-width: 768px) and (min-width: 480px) { + .menu > li { + display: table-cell; + } +} +@media all and tv { + .all-and-tv-variables { + var: all-and-tv; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/merge.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/merge.css new file mode 100644 index 000000000..4cf8c579e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/merge.css @@ -0,0 +1,22 @@ +.test1 { + transform: rotate(90deg), skew(30deg), scale(2, 4); +} +.test2 { + transform: rotate(90deg), skew(30deg); + transform: scaleX(45deg); +} +.test3 { + transform: scaleX(45deg); + background: url(data://img1.png); +} +.test4 { + transform: rotate(90deg), skew(30deg); + transform: scale(2, 4) !important; +} +.test5 { + transform: rotate(90deg), skew(30deg); + transform: scale(2, 4) !important; +} +.test6 { + transform: scale(2, 4); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-args.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-args.css new file mode 100644 index 000000000..2b6c5c962 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-args.css @@ -0,0 +1,113 @@ +#hidden { + color: transparent; +} +#hidden1 { + color: transparent; +} +.two-args { + color: blue; + width: 10px; + height: 99%; + border: 2px dotted #000000; +} +.one-arg { + width: 15px; + height: 49%; +} +.no-parens { + width: 5px; + height: 49%; +} +.no-args { + width: 5px; + height: 49%; +} +.var-args { + width: 45; + height: 17%; +} +.multi-mix { + width: 10px; + height: 29%; + margin: 4; + padding: 5; +} +body { + padding: 30px; + color: #ff0000; +} +.scope-mix { + width: 8; +} +.content { + width: 600px; +} +.content .column { + margin: 600px; +} +#same-var-name { + radius: 5px; +} +#var-inside { + width: 10px; +} +.arguments { + border: 1px solid #000000; + width: 1px; +} +.arguments2 { + border: 0px; + width: 0px; +} +.arguments3 { + border: 0px; + width: 0px; +} +.arguments4 { + border: 0 1 2 3 4; + rest: 1 2 3 4; + width: 0; +} +.edge-case { + border: "{"; + width: "{"; +} +.slash-vs-math { + border-radius: 2px/5px; + border-radius: 5px/10px; + border-radius: 6px; +} +.comma-vs-semi-colon { + one: a; + two: b, c; + one: d, e; + two: f; + one: g; + one: h; + one: i; + one: j; + one: k; + two: l; + one: m, n; + one: o, p; + two: q; + one: r, s; + two: t; +} +#named-conflict { + four: a, 11, 12, 13; + four: a, 21, 22, 23; +} +.test-mixin-default-arg { + defaults: 1px 1px 1px; + defaults: 2px 2px 2px; +} +.selector { + margin: 2, 2, 2, 2; +} +.selector2 { + margin: 2, 2, 2, 2; +} +.selector3 { + margin: 4; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-closure.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-closure.css new file mode 100644 index 000000000..b1021b6fb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-closure.css @@ -0,0 +1,9 @@ +.class { + width: 99px; +} +.overwrite { + width: 99px; +} +.nested .class { + width: 5px; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-guards.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-guards.css new file mode 100644 index 000000000..25e6f2873 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-guards.css @@ -0,0 +1,82 @@ +.light1 { + color: white; + margin: 1px; +} +.light2 { + color: black; + margin: 1px; +} +.max1 { + width: 6; +} +.max2 { + width: 8; +} +.glob1 { + margin: auto auto; +} +.ops1 { + height: gt-or-eq; + height: lt-or-eq; + height: lt-or-eq-alias; +} +.ops2 { + height: gt-or-eq; + height: not-eq; +} +.ops3 { + height: lt-or-eq; + height: lt-or-eq-alias; + height: not-eq; +} +.default1 { + content: default; +} +.test1 { + content: "true."; +} +.test2 { + content: "false."; +} +.test3 { + content: "false."; +} +.test4 { + content: "false."; +} +.test5 { + content: "false."; +} +.bool1 { + content: true and true; + content: true; + content: false, true; + content: false and true and true, true; + content: false, true and true; + content: false, false, true; + content: false, true and true and true, false; + content: not false; + content: not false and false, not false; +} +.equality-units { + test: pass; +} +.colorguardtest { + content: is #ff0000; + content: is not #0000ff its #ff0000; + content: is not #0000ff its #800080; +} +.stringguardtest { + content: is theme1; + content: is not theme2; + content: is theme1 no quotes; +} +#tryNumberPx { + catch: all; + declare: 4; + declare: 4px; +} +.call-lock-mixin .call-inner-lock-mixin { + a: 1; + x: 1; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-important.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-important.css new file mode 100644 index 000000000..b100af7ff --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-important.css @@ -0,0 +1,45 @@ +.class { + border: 1; + boxer: 1; + border-width: 1; + border: 2 !important; + boxer: 2 !important; + border-width: 2 !important; + border: 3; + boxer: 3; + border-width: 3; + border: 4 !important; + boxer: 4 !important; + border-width: 4 !important; + border: 5; + boxer: 5; + border-width: 5; + border: 0 !important; + boxer: 0 !important; + border-width: 0 !important; + border: 9 !important; + border: 9; + boxer: 9; + border-width: 9; +} +.class .inner { + test: 1; +} +.class .inner { + test: 2 !important; +} +.class .inner { + test: 3; +} +.class .inner { + test: 4 !important; +} +.class .inner { + test: 5; +} +.class .inner { + test: 0 !important; +} +.class .inner { + test: 9; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-named-args.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-named-args.css new file mode 100644 index 000000000..e460aa104 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-named-args.css @@ -0,0 +1,27 @@ +.named-arg { + color: blue; + width: 5px; + height: 99%; + args: 1px 100%; + text-align: center; +} +.class { + width: 5px; + height: 19%; + args: 1px 20%; +} +.all-args-wrong-args { + width: 10px; + height: 9%; + args: 2px 10%; +} +.named-args2 { + width: 15px; + height: 49%; + color: #646464; +} +.named-args3 { + width: 5px; + height: 29%; + color: #123456; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-nested.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-nested.css new file mode 100644 index 000000000..6378c4756 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-nested.css @@ -0,0 +1,14 @@ +.class .inner { + height: 300; +} +.class .inner .innest { + width: 30; + border-width: 60; +} +.class2 .inner { + height: 600; +} +.class2 .inner .innest { + width: 60; + border-width: 120; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-pattern.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-pattern.css new file mode 100644 index 000000000..8b8283353 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins-pattern.css @@ -0,0 +1,47 @@ +.zero { + variadic: true; + zero: 0; + one: 1; + two: 2; + three: 3; +} +.one { + variadic: true; + one: 1; + one-req: 1; + two: 2; + three: 3; +} +.two { + variadic: true; + two: 2; + three: 3; +} +.three { + variadic: true; + three-req: 3; + three: 3; +} +.left { + left: 1; +} +.right { + right: 1; +} +.border-right { + color: black; + border-right: 4px; +} +.border-left { + color: black; + border-left: 4px; +} +.only-right { + right: 33; +} +.only-left { + left: 33; +} +.left-right { + both: 330; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins.css new file mode 100644 index 000000000..32097f979 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/mixins.css @@ -0,0 +1,141 @@ +.mixin { + border: 1px solid black; +} +.mixout { + border-color: orange; +} +.borders { + border-style: dashed; +} +#namespace .borders { + border-style: dotted; +} +#namespace .biohazard { + content: "death"; +} +#namespace .biohazard .man { + color: transparent; +} +#theme > .mixin { + background-color: grey; +} +#container { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +#header .milk { + color: white; + border: 1px solid black; + background-color: grey; +} +#header #cookie { + border-style: dashed; +} +#header #cookie .chips { + border-style: dotted; +} +#header #cookie .chips .calories { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +.secure-zone { + color: transparent; +} +.direct { + border-style: dotted; +} +.bo, +.bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.amp.support { + color: orange; +} +.amp.support .higher { + top: 0px; +} +.amp.support.deeper { + height: auto; +} +.extended { + width: 100%; + border: 1px; + background: none; + color: orange; + top: 0px; + height: auto; +} +.extended .higher { + top: 0px; +} +.extended.deeper { + height: auto; +} +.do .re .mi .fa .sol .la .si { + color: cyan; +} +.mutli-selector-parents { + color: cyan; +} +.foo .bar { + width: 100%; +} +.underParents { + color: red; +} +.parent .underParents { + color: red; +} +* + h1 { + margin-top: 25px; +} +legend + h1 { + margin-top: 0; +} +h1 + * { + margin-top: 10px; +} +* + h2 { + margin-top: 20px; +} +legend + h2 { + margin-top: 0; +} +h2 + * { + margin-top: 8px; +} +* + h3 { + margin-top: 15px; +} +legend + h3 { + margin-top: 0; +} +h3 + * { + margin-top: 5px; +} +.error { + background-image: "/a.png"; + background-position: center center; +} +.test-rec .recursion { + color: black; +} +.button { + padding-left: 44px; +} +.button.large { + padding-left: 40em; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/no-output.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/no-output.css new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/operations.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/operations.css new file mode 100644 index 000000000..fb9e0aff7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/operations.css @@ -0,0 +1,49 @@ +#operations { + color: #111111; + height: 9px; + width: 3em; + substraction: 0; + division: 1; +} +#operations .spacing { + height: 9px; + width: 3em; +} +.with-variables { + height: 16em; + width: 24em; + size: 1cm; +} +.with-functions { + color: #646464; + color: #ff8080; + color: #c94a4a; +} +.negative { + height: 0px; + width: 4px; +} +.shorthands { + padding: -1px 2px 0 -4px; +} +.rem-dimensions { + font-size: 5.5rem; +} +.colors { + color: #123; + border-color: #334455; + background-color: #000000; +} +.colors .other { + color: #222222; + border-color: #222222; +} +.negations { + variable: -4px; + variable1: 0px; + variable2: 0px; + variable3: 8px; + variable4: 0px; + paren: -4px; + paren2: 16px; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/parens.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/parens.css new file mode 100644 index 000000000..412823fb1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/parens.css @@ -0,0 +1,33 @@ +.parens { + border: 2px solid #000000; + margin: 1px 3px 16 3; + width: 36; + padding: 2px 36px; +} +.more-parens { + padding: 8 4 4 4px; + width-all: 96; + width-first: 16 * 6; + width-keep: (4 * 4) * 6; + height-keep: (7 * 7) + (8 * 8); + height-all: 113; + height-parts: 49 + 64; + margin-keep: (4 * (5 + 5) / 2) - (4 * 2); + margin-parts: 20 - 8; + margin-all: 12; + border-radius-keep: 4px * (1 + 1) / 4 + 3px; + border-radius-parts: 8px / 7px; + border-radius-all: 5px; +} +.negative { + neg-var: -1; + neg-var-paren: -(1); +} +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1; +} +.mixed-units { + margin: 2px 4em 1 5pc; + padding: 6px 1em 2px 2; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/rulesets.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/rulesets.css new file mode 100644 index 000000000..408c76aad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/rulesets.css @@ -0,0 +1,33 @@ +#first > .one { + font-size: 2em; +} +#first > .one > #second .two > #deux { + width: 50%; +} +#first > .one > #second .two > #deux #third { + height: 100%; +} +#first > .one > #second .two > #deux #third:focus { + color: black; +} +#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth { + color: purple; +} +#first > .one > #second .two > #deux #fourth, +#first > .one > #second .two > #deux #five, +#first > .one > #second .two > #deux #six { + color: #110000; +} +#first > .one > #second .two > #deux #fourth .seven, +#first > .one > #second .two > #deux #five .seven, +#first > .one > #second .two > #deux #six .seven, +#first > .one > #second .two > #deux #fourth .eight > #nine, +#first > .one > #second .two > #deux #five .eight > #nine, +#first > .one > #second .two > #deux #six .eight > #nine { + border: 1px solid black; +} +#first > .one > #second .two > #deux #fourth #ten, +#first > .one > #second .two > #deux #five #ten, +#first > .one > #second .two > #deux #six #ten { + color: red; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/scope.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/scope.css new file mode 100644 index 000000000..baa055230 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/scope.css @@ -0,0 +1,35 @@ +.tiny-scope { + color: #998899; +} +.scope1 { + color: #0000ff; + border-color: #000000; +} +.scope1 .scope2 { + color: #0000ff; +} +.scope1 .scope2 .scope3 { + color: #ff0000; + border-color: #000000; + background-color: #ffffff; +} +.scope { + scoped-val: #008000; +} +.heightIsSet { + height: 1024px; +} +.useHeightInMixinCall { + mixin-height: 1024px; +} +.imported { + exists: true; +} +.testImported { + exists: true; +} +#allAreUsedHere { + default: 'top level'; + scope: 'top level'; + sub-scope-only: 'inside'; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/selectors.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/selectors.css new file mode 100644 index 000000000..510550472 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/selectors.css @@ -0,0 +1,142 @@ +h1 a:hover, +h2 a:hover, +h3 a:hover, +h1 p:hover, +h2 p:hover, +h3 p:hover { + color: red; +} +#all { + color: blue; +} +#the { + color: blue; +} +#same { + color: blue; +} +ul, +li, +div, +q, +blockquote, +textarea { + margin: 0; +} +td { + margin: 0; + padding: 0; +} +td, +input { + line-height: 1em; +} +a { + color: red; +} +a:hover { + color: blue; +} +div a { + color: green; +} +p a span { + color: yellow; +} +.foo .bar .qux, +.foo .baz .qux { + display: block; +} +.qux .foo .bar, +.qux .foo .baz { + display: inline; +} +.qux.foo .bar, +.qux.foo .baz { + display: inline-block; +} +.qux .foo .bar .biz, +.qux .foo .baz .biz { + display: none; +} +.a.b.c { + color: red; +} +.c .b.a { + color: red; +} +.foo .p.bar { + color: red; +} +.foo.p.bar { + color: red; +} +.foo + .foo { + background: amber; +} +.foo + .foo { + background: amber; +} +.foo + .foo, +.foo + .bar, +.bar + .foo, +.bar + .bar { + background: amber; +} +.foo a > .foo a, +.foo a > .bar a, +.foo a > .foo b, +.foo a > .bar b, +.bar a > .foo a, +.bar a > .bar a, +.bar a > .foo b, +.bar a > .bar b, +.foo b > .foo a, +.foo b > .bar a, +.foo b > .foo b, +.foo b > .bar b, +.bar b > .foo a, +.bar b > .bar a, +.bar b > .foo b, +.bar b > .bar b { + background: amber; +} +.other ::fnord { + color: #ff0000; +} +.other::fnord { + color: #ff0000; +} +.other ::bnord { + color: #ff0000; +} +.other::bnord { + color: #ff0000; +} +.blood { + color: red; +} +.bloodred { + color: green; +} +#blood.blood.red.black { + color: black; +} +:nth-child(3) { + selector: interpolated; +} +.test:nth-child(odd):not(:nth-child(3)) { + color: #ff0000; +} +[prop], +[prop=10%], +[prop="value3"], +[prop*="val3"], +[|prop~="val3"], +[*|prop$="val3"], +[ns|prop^="val3"], +[3^="val3"], +[3=3], +[3] { + attributes: yes; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/static-urls/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/static-urls/urls.css new file mode 100644 index 000000000..95f04fbb7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/static-urls/urls.css @@ -0,0 +1,41 @@ +@import "css/background.css"; +@import "folder (1)/import-test-d.css"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(folder\ \(1\)/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(folder\ \(1\)/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(folder\ \(1\)/bg.jpg) no-repeat, url(folder\ \(1\)/bg.png) repeat-x top left, url(folder\ \(1\)/bg); +} +.values { + url: url('folder (1)/Trebuchet'); +} +#logo { + width: 100px; + height: 100px; + background: url('assets/logo.png'); +} +@font-face { + font-family: xecret; + src: url('assets/xecret.ttf'); +} +#secret { + font-family: xecret, sans-serif; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/strings.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/strings.css new file mode 100644 index 000000000..cd6d60202 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/strings.css @@ -0,0 +1,43 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: DX.Transform.MS.BS.filter(opacity=50); +} +#one-line { + image: url(http://tooks.com); +} +#crazy { + image: url(http://), "}", url("http://}"); +} +#interpolation { + url: "http://lesscss.org/dev/image.jpg"; + url2: "http://lesscss.org/image-256.jpg"; + url3: "http://lesscss.org#445566"; + url4: "http://lesscss.org/hello"; + url5: "http://lesscss.org/54.4px"; +} +.mix-mul-class { + color: #0000ff; + color: #ff0000; + color: #000000; + color: #ffa500; +} +.watermark { + family: Univers, Arial, Verdana, San-Serif; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/urls.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/urls.css new file mode 100644 index 000000000..492f5bc12 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/urls.css @@ -0,0 +1,63 @@ +@import "css/background.css"; +@import "import/import-test-d.css"; +@import "file.css"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; + background: url("img.jpg") center / 100px; + background: #ffffff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); + background-image: url("http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700"); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + url: url('Trebuchet'); +} +#logo { + width: 100px; + height: 100px; + background: url('import/assets/logo.png'); +} +@font-face { + font-family: xecret; + src: url('import/assets/xecret.ttf'); +} +#secret { + font-family: xecret, sans-serif; +} +#data-uri { + uri: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg=='); +} +#data-uri-guess { + uri: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg=='); +} +#data-uri-ascii { + uri-1: url('data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A'); + uri-2: url('data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A'); +} +#data-uri-toobig { + uri: url('../data/data-uri-fail.png'); +} +#svg-functions { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkaWVudCkiIC8+PC9zdmc+'); + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg=='); + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIxJSIgc3RvcC1jb2xvcj0iI2M0YzRjNCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDA4MDAwIi8+PHN0b3Agb2Zmc2V0PSI5NSUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg=='); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/variables.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/variables.css new file mode 100644 index 000000000..f8d8518b9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/variables.css @@ -0,0 +1,45 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS", Verdana, sans-serif; + quotes: "~" "~"; +} +.redef { + zero: 0; +} +.redef .inition { + three: 3; +} +.values { + minus-one: -1; + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +.testPollution { + a: 'no-pollution'; +} +.units { + width: 1px; + same-unit-as-previously: 1px; + square-pixel-divided: 1px; + odd-unit: 2; + percentage: 500%; + pixels: 500px; + conversion-metric-a: 30mm; + conversion-metric-b: 3cm; + conversion-imperial: 3in; + custom-unit: 420octocats; + custom-unit-cancelling: 18dogs; + mix-units: 2px; + invalid-units: 1px; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/css/whitespace.css b/node_modules/grunt-contrib-less/node_modules/less/test/css/whitespace.css new file mode 100644 index 000000000..74c9b65e6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/css/whitespace.css @@ -0,0 +1,42 @@ +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white ; +} +.white, +.space, +.mania { + color: white; +} +.no-semi-column { + color: #ffffff; +} +.no-semi-column { + color: white; + white-space: pre; +} +.no-semi-column { + border: 2px solid #ffffff; +} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.sel .newline_ws .tab_ws { + color: white; + background-position: 45 -23; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/data/data-uri-fail.png b/node_modules/grunt-contrib-less/node_modules/less/test/data/data-uri-fail.png new file mode 100644 index 000000000..f91b59fb3 Binary files /dev/null and b/node_modules/grunt-contrib-less/node_modules/less/test/data/data-uri-fail.png differ diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/data/image.jpg b/node_modules/grunt-contrib-less/node_modules/less/test/data/image.jpg new file mode 100644 index 000000000..83f777909 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/data/image.jpg @@ -0,0 +1 @@ +not actually a jpeg file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/data/page.html b/node_modules/grunt-contrib-less/node_modules/less/test/data/page.html new file mode 100644 index 000000000..ccdfe565d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/data/page.html @@ -0,0 +1 @@ +

    This page is 100% Awesome.

    diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less-test.js b/node_modules/grunt-contrib-less/node_modules/less/test/less-test.js new file mode 100644 index 000000000..331cf761d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less-test.js @@ -0,0 +1,260 @@ +/*jshint latedef: nofunc */ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var less = require('../lib/less'); +var stylize = require('../lib/less/lessc_helper').stylize; + +var globals = Object.keys(global); + +var oneTestOnly = process.argv[2]; + +var isVerbose = process.env.npm_config_loglevel === 'verbose'; + +var totalTests = 0, + failedTests = 0, + passedTests = 0; + +less.tree.functions.add = function (a, b) { + return new(less.tree.Dimension)(a.value + b.value); +}; +less.tree.functions.increment = function (a) { + return new(less.tree.Dimension)(a.value + 1); +}; +less.tree.functions._color = function (str) { + if (str.value === "evil red") { return new(less.tree.Color)("600"); } +}; + +console.log("\n" + stylize("LESS", 'underline') + "\n"); + +runTestSet({strictMath: true, relativeUrls: true, silent: true}); +runTestSet({strictMath: true, strictUnits: true}, "errors/", + testErrors, null, getErrorPathReplacementFunction("errors")); +runTestSet({strictMath: true, strictUnits: true, javascriptEnabled: false}, "no-js-errors/", + testErrors, null, getErrorPathReplacementFunction("no-js-errors")); +runTestSet({strictMath: true, dumpLineNumbers: 'comments'}, "debug/", null, + function(name) { return name + '-comments'; }); +runTestSet({strictMath: true, dumpLineNumbers: 'mediaquery'}, "debug/", null, + function(name) { return name + '-mediaquery'; }); +runTestSet({strictMath: true, dumpLineNumbers: 'all'}, "debug/", null, + function(name) { return name + '-all'; }); +runTestSet({strictMath: true, relativeUrls: false, rootpath: "folder (1)/"}, "static-urls/"); +runTestSet({strictMath: true, compress: true}, "compression/"); +runTestSet({}, "legacy/"); +runTestSet({strictMath: true, strictUnits: true, sourceMap: true }, "sourcemaps/", + testSourcemap, null, null, function(filename) { return path.join('test/sourcemaps', filename) + '.json'; }); + +testNoOptions(); + +function getErrorPathReplacementFunction(dir) { + return function(input) { + return input.replace( + "{path}", path.join(process.cwd(), "/test/less/" + dir + "/")) + .replace("{pathrel}", path.join("test", "less", dir + "/")) + .replace("{pathhref}", "") + .replace("{404status}", "") + .replace(/\r\n/g, '\n'); + }; +} + +function testSourcemap(name, err, compiledLess, doReplacements, sourcemap) { + fs.readFile(path.join('test/', name) + '.json', 'utf8', function (e, expectedSourcemap) { + sys.print("- " + name + ": "); + if (sourcemap === expectedSourcemap) { + ok('OK'); + } else if (err) { + fail("ERROR: " + (err && err.message)); + if (isVerbose) { + console.error(); + console.error(err.stack); + } + } else { + difference("FAIL", expectedSourcemap, sourcemap); + } + }); +} + +function testErrors(name, err, compiledLess, doReplacements) { + fs.readFile(path.join('test/less/', name) + '.txt', 'utf8', function (e, expectedErr) { + sys.print("- " + name + ": "); + expectedErr = doReplacements(expectedErr, 'test/less/errors/'); + if (!err) { + if (compiledLess) { + fail("No Error", 'red'); + } else { + fail("No Error, No Output"); + } + } else { + var errMessage = less.formatError(err); + if (errMessage === expectedErr) { + ok('OK'); + } else { + difference("FAIL", expectedErr, errMessage); + } + } + }); +} + +function globalReplacements(input, directory) { + var p = path.join(process.cwd(), directory), + pathimport = path.join(process.cwd(), directory + "import/"), + pathesc = p.replace(/[.:/\\]/g, function(a) { return '\\' + (a=='\\' ? '\/' : a); }), + pathimportesc = pathimport.replace(/[.:/\\]/g, function(a) { return '\\' + (a=='\\' ? '\/' : a); }); + + return input.replace(/\{path\}/g, p) + .replace(/\{pathesc\}/g, pathesc) + .replace(/\{pathimport\}/g, pathimport) + .replace(/\{pathimportesc\}/g, pathimportesc) + .replace(/\r\n/g, '\n'); +} + +function checkGlobalLeaks() { + return Object.keys(global).filter(function(v) { + return globals.indexOf(v) < 0; + }); +} + +function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements, getFilename) { + foldername = foldername || ""; + + if(!doReplacements) { + doReplacements = globalReplacements; + } + + fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) { + if (! /\.less/.test(file)) { return; } + + var name = foldername + path.basename(file, '.less'); + + if (oneTestOnly && name !== oneTestOnly) { + return; + } + + totalTests++; + + if (options.sourceMap) { + var sourceMapOutput; + options.writeSourceMap = function(output) { + sourceMapOutput = output; + }; + options.sourceMapOutputFilename = name + ".css"; + options.sourceMapBasepath = path.join(process.cwd(), "test/less"); + options.sourceMapRootpath = "testweb/"; + } + + toCSS(options, path.join('test/less/', foldername + file), function (err, less) { + + if (verifyFunction) { + return verifyFunction(name, err, less, doReplacements, sourceMapOutput); + } + var css_name = name; + if(nameModifier) { css_name = nameModifier(name); } + fs.readFile(path.join('test/css', css_name) + '.css', 'utf8', function (e, css) { + sys.print("- " + css_name + ": "); + + css = css && doReplacements(css, 'test/less/' + foldername); + if (less === css) { ok('OK'); } + else if (err) { + fail("ERROR: " + (err && err.message)); + if (isVerbose) { + console.error(); + console.error(err.stack); + } + } else { + difference("FAIL", css, less); + } + }); + }); + }); +} + +function diff(left, right) { + require('diff').diffLines(left, right).forEach(function(item) { + if(item.added || item.removed) { + var text = item.value.replace("\n", String.fromCharCode(182) + "\n"); + sys.print(stylize(text, item.added ? 'green' : 'red')); + } else { + sys.print(item.value); + } + }); + console.log(""); +} + +function fail(msg) { + console.error(stylize(msg, 'red')); + failedTests++; + endTest(); +} + +function difference(msg, left, right) { + console.warn(stylize(msg, 'yellow')); + failedTests++; + + diff(left, right); + endTest(); +} + +function ok(msg) { + console.log(stylize(msg, 'green')); + passedTests++; + endTest(); +} + +function endTest() { + var leaked = checkGlobalLeaks(); + if (failedTests + passedTests === totalTests) { + console.log(""); + if (failedTests > 0) { + console.error(failedTests + stylize(" Failed", "red") + ", " + passedTests + " passed"); + } else { + console.log(stylize("All Passed ", "green") + passedTests + " run"); + } + if (leaked.length > 0) { + console.log(""); + console.warn(stylize("Global leak detected: ", "red") + leaked.join(', ')); + } + + if (leaked.length || failedTests) { + //process.exit(1); + process.on('exit', function() { process.reallyExit(1) }); + } + } +} + +function toCSS(options, path, callback) { + var css; + options = options || {}; + fs.readFile(path, 'utf8', function (e, str) { + if (e) { return callback(e); } + + options.paths = [require('path').dirname(path)]; + options.filename = require('path').resolve(process.cwd(), path); + options.optimization = options.optimization || 0; + + new(less.Parser)(options).parse(str, function (err, tree) { + if (err) { + callback(err); + } else { + try { + css = tree.toCSS(options); + callback(null, css); + } catch (e) { + callback(e); + } + } + }); + }); +} + +function testNoOptions() { + totalTests++; + try { + sys.print("- Integration - creating parser without options: "); + new(less.Parser)(); + } catch(e) { + fail(stylize("FAIL\n", "red")); + return; + } + ok(stylize("OK\n", "green")); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/charsets.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/charsets.less new file mode 100644 index 000000000..550d40e97 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/charsets.less @@ -0,0 +1,3 @@ +@charset "UTF-8"; + +@import "import/import-charset-test"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/colors.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/colors.less new file mode 100644 index 000000000..656ca6364 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/colors.less @@ -0,0 +1,92 @@ +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } + #argb { + color: argb(rgba(255, 238, 170, 0.1)); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } + #argb { + color: argb(rgba(0, 0, 255, 0.1)); + } +} + +#alpha #hsla { + color: hsla(11, 20%, 20%, 0.6); +} + +#overflow { + .a { color: (#111111 - #444444); } // #000000 + .b { color: (#eee + #fff); } // #ffffff + .c { color: (#aaa * 3); } // #ffffff + .d { color: (#00ee00 + #009900); } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#333333 { + color: rgb(20%, 20%, 20%); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} + +.lightenblue { + color: lighten(blue, 10%); +} + +.darkenblue { + color: darken(blue, 10%); +} + +.unknowncolors { + color: blue2; + border: 2px solid superred; +} + +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha { + @colorvar: rgba(150, 200, 150, 0.7); + #fromvar { + opacity: alpha(@colorvar); + } + #short { + opacity: alpha(#aaa); + } + #long { + opacity: alpha(#bababa); + } + #rgba { + opacity: alpha(rgba(50, 120, 95, 0.2)); + } + #hsl { + opacity: alpha(hsl(120, 100%, 50%)); + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/comments.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/comments.less new file mode 100644 index 000000000..7859911e3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/comments.less @@ -0,0 +1,83 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo *//* boo again*/, +//.commented_out1 +//.commented_out2 +//.commented_out3 +.comments //end of comments1 +//end of comments2 +{ + /**/ // An empty comment + color: red; /* A C-style comment */ /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; // }{ '" + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +.selector /* .with */, .lots, /* of */ .comments { + color: grey, /* blue */ orange; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: (2px * 4) /* moz only with operation */; +} + +.mixin_def_with_colors(@a: white, // in + @b: 1px //put in @b - causes problems! ---> + ) // the + when (@a = white) { + .test { + color: @b; + } +} +.mixin_def_with_colors(); + +#last { color: blue } +// + +/* *//* { *//* *//* *//* */#div { color:#A33; }/* } */ diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/compression/compression.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/compression/compression.less new file mode 100644 index 000000000..e6a0fe798 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/compression/compression.less @@ -0,0 +1,32 @@ +#colours { + color1: #fea; + color2: #ffeeaa; + color3: rgba(255, 238, 170, 0.1); + @color1: #fea; + string: "@{color1}"; + /* comments are stripped */ + // both types! + /*! but not this type + Note preserved whitespace + */ +} +dimensions { + val: 0.1px; + val: 0em; + val: 4cm; + val: 0.2; + val: 5; + angles-must-have-unit: 0deg; + durations-must-have-unit: 0s; + length-doesnt-have-unit: 0px; + width: auto\9; +} +@page { + marks: none; +@top-left-corner { + vertical-align: top; +} +@top-left { + vertical-align: top; +} +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/css-3.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-3.less new file mode 100644 index 000000000..c31a6eb26 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-3.less @@ -0,0 +1,125 @@ +.comma-delimited { + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; + -webkit-transform: rotate(-0.0000000001deg); +} +@font-face { + font-family: Headline; + unicode-range: U+??????, U+0???, U+0-7F, U+A5; +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} + +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} + +@-webkit-keyframes frames { + 0% { border: 1px } + 5.5% { border: 2px } + 100% { border: 3px } +} + +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from,to { + font-size: 12px; + } + 0%,100% { + font-size: 12px; + } +} + +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} + +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} + +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} + +@viewport { + font-size: 10px; +} +@namespace foo url(http://www.example.com); + +foo|h1 { color: blue; } +foo|* { color: yellow; } +|h1 { color: red; } +*|h1 { color: green; } +h1 { color: green; } +.upper-test { + UpperCaseProperties: allowed; +} +@host { + div { + display: block; + } +} +::distributed(input::placeholder) { + color: #b3b3b3; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/css-escapes.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-escapes.less new file mode 100644 index 000000000..6a4b28306 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-escapes.less @@ -0,0 +1,33 @@ +@ugly: fuchsia; + +.escape\|random\|char { + color: red; +} + +.mixin\!tUp { + font-weight: bold; +} + +// class="404" +.\34 04 { + background: red; + + strong { + color: @ugly; + .mixin\!tUp; + } +} + +.trailingTest\+ { + color: red; +} + +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} + +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/css-guards.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-guards.less new file mode 100644 index 000000000..41fbfbf50 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/css-guards.less @@ -0,0 +1,64 @@ + +.light when (lightness(@a) > 50%) { + color: green; +} +.dark when (lightness(@a) < 50%) { + color: orange; +} +@a: #ddd; + +.see-the { + @a: #444; // this mirrors what mixins do - they evaluate guards at the point of execution + .light(); + .dark(); +} + +.hide-the { + .light(); + .dark(); +} + +.multiple-conditions-1 when (@b = 1), (@c = 2), (@d = 3) { + color: red; +} + +.multiple-conditions-2 when (@b = 1), (@c = 2), (@d = 2) { + color: blue; +} + +@b: 2; +@c: 3; +@d: 3; + +.inheritance when (@b = 2) { + .test { + color: black; + } + &:hover { + color: pink; + } + .hideme when (@b = 1) { + color: green; + } + & when (@b = 1) { + hideme: green; + } +} + +.hideme when (@b = 1) { + .test { + color: black; + } + &:hover { + color: pink; + } + .hideme when (@b = 1) { + color: green; + } +} + +& when (@b = 1) { + .hideme { + color: red; + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/css.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/css.less new file mode 100644 index 000000000..766bdd4d0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/css.less @@ -0,0 +1,108 @@ +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + * { + font-size: 3em; + } +} + +@media screen { + * { + font-size: 10px; + } +} + +@font-face { + font-family: 'Garamond Pro'; +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: +2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; + border-radius: 5px / 10px; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; + .nested-multiple { + multiple-semi-colons: yes;;;;;; + }; + filter: alpha(opacity=100); + width: auto\9; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +.def-font(@name) { + @font-face { + font-family: @name + } +} + +.def-font(font-a); +.def-font(font-b); + +.æøå { + margin: 0; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/import/test.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/import/test.less new file mode 100644 index 000000000..795082f5a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/import/test.less @@ -0,0 +1,25 @@ +@charset "ISO-8859-1"; + +.mixin_import1() { + @media all { + .tst { + color: black; + @media screen { + color: red; + .tst3 { + color: white; + } + } + } + } +} + +.mixin_import2() { + .tst2 { + color: white; + } +} + +.tst3 { + color: grey; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/linenumbers.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/linenumbers.less new file mode 100644 index 000000000..172ba028f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/debug/linenumbers.less @@ -0,0 +1,23 @@ +@charset "UTF-8"; + +@import "import/test.less"; + +.start() { + .test2 { + color: red; + } +} + +.mix() { + color: black; +} + +.test1 { + .mix(); +} + +.start(); + +.mixin_import1(); + +.mixin_import2(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.less new file mode 100644 index 000000000..9b708de93 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.less @@ -0,0 +1,3 @@ +.a { + error: (1px + 3em); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.txt new file mode 100644 index 000000000..b5553618e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units.txt @@ -0,0 +1,2 @@ +SyntaxError: Incompatible units. Change the units or use the unit function. Bad units: 'px' and 'em'. in {path}add-mixed-units.less on line null, column 0: +1 error: (1px + 3em); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.less new file mode 100644 index 000000000..266311605 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.less @@ -0,0 +1,3 @@ +.a { + error: ((1px * 2px) + (3em * 3px)); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.txt new file mode 100644 index 000000000..cc65a760a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/add-mixed-units2.txt @@ -0,0 +1,2 @@ +SyntaxError: Incompatible units. Change the units or use the unit function. Bad units: 'px*px' and 'em*px'. in {path}add-mixed-units2.less on line null, column 0: +1 error: ((1px * 2px) + (3em * 3px)); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.less new file mode 100644 index 000000000..c2dc6ac0e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.less @@ -0,0 +1 @@ +@@demo: "hi"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.txt new file mode 100644 index 000000000..5ae9d4a41 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/bad-variable-declaration1.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}bad-variable-declaration1.less on line 1, column 1: +1 @@demo: "hi"; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.less new file mode 100644 index 000000000..bc1b48099 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.less @@ -0,0 +1,3 @@ +.test { + color: color("NOT A COLOR"); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.txt new file mode 100644 index 000000000..aa8d47059 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-func-invalid-color.txt @@ -0,0 +1,4 @@ +ArgumentError: error evaluating function `color`: argument must be a color keyword or 3/6 digit hex e.g. #FFF in {path}color-func-invalid-color.less on line 2, column 10: +1 .test { +2 color: color("NOT A COLOR"); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.less new file mode 100644 index 000000000..7c60c0047 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.less @@ -0,0 +1,3 @@ +.a { + prop: (3 / #fff); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.txt new file mode 100644 index 000000000..1b3f889fc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/color-operation-error.txt @@ -0,0 +1,2 @@ +OperationError: Can't substract or divide a color from a number in {path}color-operation-error.less on line null, column 0: +1 prop: (3 / #fff); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.less new file mode 100644 index 000000000..a7d263965 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.less @@ -0,0 +1 @@ +#gaga /* Comment */ span { color: red } \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.txt new file mode 100644 index 000000000..e48f878ca --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/comment-in-selector.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}comment-in-selector.less on line 1, column 21: +1 #gaga /* Comment */ span { color: red } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.less new file mode 100644 index 000000000..d228b7c47 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.less @@ -0,0 +1,3 @@ +.a { + error: (1px / 3em); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.txt new file mode 100644 index 000000000..c189d2aad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/divide-mixed-units.txt @@ -0,0 +1,4 @@ +SyntaxError: Multiple units in dimension. Correct the units or use the unit function. Bad unit: px/em in {path}divide-mixed-units.less on line 2, column 3: +1 .a { +2 error: (1px / 3em); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.less new file mode 100644 index 000000000..84689ef39 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.less @@ -0,0 +1,3 @@ +:extend(.a all) { + property: red; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.txt new file mode 100644 index 000000000..bd2e3cd75 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-no-selector.txt @@ -0,0 +1,3 @@ +SyntaxError: Extend must be used to extend a selector, it cannot be used on its own in {path}extend-no-selector.less on line 1, column 17: +1 :extend(.a all) { +2 property: red; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.less new file mode 100644 index 000000000..90ee512c5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.less @@ -0,0 +1,3 @@ +.a:extend(.b all).c { + property: red; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.txt new file mode 100644 index 000000000..32ebedfc4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/extend-not-at-end.txt @@ -0,0 +1,3 @@ +SyntaxError: Extend can only be used at the end of selector in {path}extend-not-at-end.less on line 1, column 21: +1 .a:extend(.b all).c { +2 property: red; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.less new file mode 100644 index 000000000..5ce8e4d9e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.less @@ -0,0 +1,6 @@ +.a { + color: green; + // tests line number for import reference is correct +} + +@import "file-does-not-exist.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.txt new file mode 100644 index 000000000..488d154a8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-missing.txt @@ -0,0 +1,3 @@ +FileError: '{pathhref}file-does-not-exist.less' wasn't found{404status} in {path}import-missing.less on line 6, column 1: +5 +6 @import "file-does-not-exist.less"; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.less new file mode 100644 index 000000000..bf2c7f65f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.less @@ -0,0 +1 @@ +@import "this-statement-is-invalid.less" \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.txt new file mode 100644 index 000000000..8b3f795cf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-no-semi.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}import-no-semi.less on line 1, column 1: +1 @import "this-statement-is-invalid.less" diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.less new file mode 100644 index 000000000..4280673b5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.less @@ -0,0 +1 @@ +@import "imports/import-subfolder1.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.txt new file mode 100644 index 000000000..976292765 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder1.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less on line 11, column 1: +10 +11 .mixin-not-defined(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.less new file mode 100644 index 000000000..a6b9b9ce9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.less @@ -0,0 +1 @@ +@import "imports/import-subfolder2.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.txt new file mode 100644 index 000000000..7d514efc8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/import-subfolder2.txt @@ -0,0 +1,2 @@ +ParseError: missing opening `{` in {path}parse-error-curly-bracket.less on line 1, column 2: +1 }} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder1.less new file mode 100644 index 000000000..24ec0532a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder1.less @@ -0,0 +1 @@ +@import "subfolder/mixin-not-defined.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder2.less new file mode 100644 index 000000000..6058ad14e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-subfolder2.less @@ -0,0 +1 @@ +@import "subfolder/parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-test.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-test.less new file mode 100644 index 000000000..a91ae0544 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/import-test.less @@ -0,0 +1,4 @@ +.someclass +{ + font-weight: bold; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less new file mode 100644 index 000000000..2bb2d0916 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less @@ -0,0 +1 @@ +@import "../../mixin-not-defined.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less new file mode 100644 index 000000000..f37fa9d00 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less @@ -0,0 +1 @@ +@import "../../parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.less new file mode 100644 index 000000000..9cffb9ff0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.less @@ -0,0 +1,3 @@ +.scope { + var: `this.foo.toJS()`; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.txt new file mode 100644 index 000000000..3c83a966e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/javascript-error.txt @@ -0,0 +1,4 @@ +SyntaxError: JavaScript evaluation error: 'TypeError: Cannot call method 'toJS' of undefined' in {path}javascript-error.less on line 2, column 27: +1 .scope { +2 var: `this.foo.toJS()`; +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less new file mode 100644 index 000000000..9b0e23afa --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less @@ -0,0 +1,6 @@ +.mixin(@a : 4, @b : 3, @c: 2) { + will: fail; +} +.mixin-test { + .mixin(@a: 5; @b: 6, @c: 7); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt new file mode 100644 index 000000000..a07f5e9d9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt @@ -0,0 +1,4 @@ +SyntaxError: Cannot mix ; and , as delimiter types in {path}mixed-mixin-definition-args-1.less on line 5, column 30: +4 .mixin-test { +5 .mixin(@a: 5; @b: 6, @c: 7); +6 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less new file mode 100644 index 000000000..c9709427a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less @@ -0,0 +1,6 @@ +.mixin(@a : 4, @b : 3, @c: 2) { + will: fail; +} +.mixin-test { + .mixin(@a: 5, @b: 6; @c: 7); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt new file mode 100644 index 000000000..fa00183b2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt @@ -0,0 +1,4 @@ +SyntaxError: Cannot mix ; and , as delimiter types in {path}mixed-mixin-definition-args-2.less on line 5, column 26: +4 .mixin-test { +5 .mixin(@a: 5, @b: 6; @c: 7); +6 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.less new file mode 100644 index 000000000..e2dad5cea --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.less @@ -0,0 +1,11 @@ + +.error-is-further-on() { +} + +.pad-here-to-reproduce-error-in() { +} + +.the-import-subfolder-test() { +} + +.mixin-not-defined(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.txt new file mode 100644 index 000000000..976292765 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-defined.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less on line 11, column 1: +10 +11 .mixin-not-defined(); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.less new file mode 100644 index 000000000..be0d6b1a1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.less @@ -0,0 +1,6 @@ +@saxofon:trumpete; + +.mixin(saxofon) { +} + +.mixin(@saxofon); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.txt new file mode 100644 index 000000000..57df97728 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched.txt @@ -0,0 +1,3 @@ +RuntimeError: No matching definition was found for `.mixin(trumpete)` in {path}mixin-not-matched.less on line 6, column 1: +5 +6 .mixin(@saxofon); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.less new file mode 100644 index 000000000..14f44bf32 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.less @@ -0,0 +1,6 @@ +@saxofon:trumpete; + +.mixin(@a, @b) { +} + +.mixin(@a: @saxofon); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.txt new file mode 100644 index 000000000..dceedaf05 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/mixin-not-matched2.txt @@ -0,0 +1,3 @@ +RuntimeError: No matching definition was found for `.mixin(@a:trumpete)` in {path}mixin-not-matched2.less on line 6, column 1: +5 +6 .mixin(@a: @saxofon); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.less new file mode 100644 index 000000000..4eabb60a1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.less @@ -0,0 +1,4 @@ +@ie8: true; +.a when (@ie8 = true), +.b { +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.txt new file mode 100644 index 000000000..3d23e26bc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiple-guards-on-css-selectors.txt @@ -0,0 +1,4 @@ +SyntaxError: Guards are only currently allowed on a single selector. in {path}multiple-guards-on-css-selectors.less on line 3, column 1: +2 .a when (@ie8 = true), +3 .b { +4 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.less new file mode 100644 index 000000000..ff983a85e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.less @@ -0,0 +1,7 @@ +/* Test */ +#blah { + // blah +} +.a { + error: (1px * 1em); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.txt new file mode 100644 index 000000000..9ed834f1d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/multiply-mixed-units.txt @@ -0,0 +1,4 @@ +SyntaxError: Multiple units in dimension. Correct the units or use the unit function. Bad unit: em*px in {path}multiply-mixed-units.less on line 6, column 3: +5 .a { +6 error: (1px * 1em); +7 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.less new file mode 100644 index 000000000..7c8ec10e6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.less @@ -0,0 +1,3 @@ +.a { + something: (12 (13 + 5 -23) + 5); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.txt new file mode 100644 index 000000000..6fc40ac0b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-1.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '(' in {path}parens-error-1.less on line 2, column 18: +1 .a { +2 something: (12 (13 + 5 -23) + 5); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.less new file mode 100644 index 000000000..4a392b8ee --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.less @@ -0,0 +1,3 @@ +.a { + something: (12 * (13 + 5 -23)); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.txt new file mode 100644 index 000000000..cee5c52d1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-2.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '-' in {path}parens-error-2.less on line 2, column 28: +1 .a { +2 something: (12 * (13 + 5 -23)); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.less new file mode 100644 index 000000000..9e6d5405b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.less @@ -0,0 +1,3 @@ +.a { + something: (12 + (13 + 10 -23)); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.txt new file mode 100644 index 000000000..3280ef04e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parens-error-3.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '-' in {path}parens-error-3.less on line 2, column 29: +1 .a { +2 something: (12 + (13 + 10 -23)); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.less new file mode 100644 index 000000000..a2950a11c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.less @@ -0,0 +1 @@ +}} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.txt new file mode 100644 index 000000000..7d514efc8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-curly-bracket.txt @@ -0,0 +1,2 @@ +ParseError: missing opening `{` in {path}parse-error-curly-bracket.less on line 1, column 2: +1 }} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.less new file mode 100644 index 000000000..144a6edf7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.less @@ -0,0 +1,2 @@ +body { + background-color: #fff; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.txt new file mode 100644 index 000000000..0005f4641 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-missing-bracket.txt @@ -0,0 +1,3 @@ +ParseError: missing closing `}` in {path}parse-error-missing-bracket.less on line 3, column 1: +2 background-color: #fff; +3 diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.less new file mode 100644 index 000000000..6be3de853 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.less @@ -0,0 +1,13 @@ +@import 'import/import-test.less'; + +body +{ + font-family: arial, sans-serif; +} + +nonsense; + +.clickable +{ + cursor: pointer; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.txt new file mode 100644 index 000000000..07732c929 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/parse-error-with-import.txt @@ -0,0 +1,4 @@ +ParseError: Unrecognised input in {path}parse-error-with-import.less on line 8, column 9: +7 +8 nonsense; +9 diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.less new file mode 100644 index 000000000..51bf6e397 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.less @@ -0,0 +1,3 @@ +.test { + display/*/: block; /*sorry for IE5*/ +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.txt new file mode 100644 index 000000000..e42ef90eb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-ie5-hack.txt @@ -0,0 +1,4 @@ +ParseError: Unrecognised input in {path}property-ie5-hack.less on line 2, column 3: +1 .test { +2 display/*/: block; /*sorry for IE5*/ +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.less new file mode 100644 index 000000000..8fed4be3b --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.less @@ -0,0 +1,4 @@ +.a() { + prop:1; +} +.a(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.txt new file mode 100644 index 000000000..04b277660 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root.txt @@ -0,0 +1,4 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +1 .a() { +2 prop:1; +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.less new file mode 100644 index 000000000..ce8656d17 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.less @@ -0,0 +1 @@ +@import "property-in-root"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.txt new file mode 100644 index 000000000..04b277660 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root2.txt @@ -0,0 +1,4 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +1 .a() { +2 prop:1; +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.less new file mode 100644 index 000000000..056c2f72a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.less @@ -0,0 +1,4 @@ +prop:1; +.a { + prop:1; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.txt new file mode 100644 index 000000000..68ef9454d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/property-in-root3.txt @@ -0,0 +1,3 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root3.less on line 1, column 1: +1 prop:1; +2 .a { diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.less new file mode 100644 index 000000000..c1ca75f11 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.less @@ -0,0 +1 @@ +@bodyColor: darken(@bodyColor, 30%); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.txt new file mode 100644 index 000000000..eb616e7d2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/recursive-variable.txt @@ -0,0 +1,2 @@ +NameError: Recursive variable definition for @bodyColor in {path}recursive-variable.less on line 1, column 20: +1 @bodyColor: darken(@bodyColor, 30%); diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.less new file mode 100644 index 000000000..c069ff724 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.less @@ -0,0 +1,3 @@ +.a { + a: svg-gradient(horizontal, black, white); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.txt new file mode 100644 index 000000000..ec662fe60 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient1.txt @@ -0,0 +1,4 @@ +ArgumentError: error evaluating function `svg-gradient`: svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center' in {path}svg-gradient1.less on line 2, column 6: +1 .a { +2 a: svg-gradient(horizontal, black, white); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.less new file mode 100644 index 000000000..ff14ef110 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.less @@ -0,0 +1,3 @@ +.a { + a: svg-gradient(to bottom, black, orange, 45%, white); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.txt new file mode 100644 index 000000000..7004115f7 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient2.txt @@ -0,0 +1,4 @@ +ArgumentError: error evaluating function `svg-gradient`: svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position] in {path}svg-gradient2.less on line 2, column 6: +1 .a { +2 a: svg-gradient(to bottom, black, orange, 45%, white); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.less new file mode 100644 index 000000000..8f1852460 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.less @@ -0,0 +1,3 @@ +.a { + a: svg-gradient(black, orange); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.txt new file mode 100644 index 000000000..eb0b483e3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/svg-gradient3.txt @@ -0,0 +1,4 @@ +ArgumentError: error evaluating function `svg-gradient`: svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position] in {path}svg-gradient3.less on line 2, column 6: +1 .a { +2 a: svg-gradient(black, orange); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.less new file mode 100644 index 000000000..119e9818f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.less @@ -0,0 +1,3 @@ +.a { + font-size: unit(80/16,rem); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.txt new file mode 100644 index 000000000..baf90f422 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/errors/unit-function.txt @@ -0,0 +1,4 @@ +ArgumentError: error evaluating function `unit`: the first argument to unit must be a number. Have you forgotten parenthesis? in {path}unit-function.less on line 2, column 14: +1 .a { +2 font-size: unit(80/16,rem); +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-chaining.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-chaining.less new file mode 100644 index 000000000..aad221ea6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-chaining.less @@ -0,0 +1,91 @@ +//very simple chaining +.a { + color: black; +} +.b:extend(.a) {} +.c:extend(.b) {} + +//very simple chaining, ordering not important + +.d:extend(.e) {} +.e:extend(.f) {} +.f { + color: black; +} + +//extend with all + +.g.h { + color: black; +} +.i.j:extend(.g all) { + color: white; +} +.k:extend(.i all) {} + +//extend multi-chaining + +.l { + color: black; +} +.m:extend(.l){} +.n:extend(.m){} +.o:extend(.n){} +.p:extend(.o){} +.q:extend(.p){} +.r:extend(.q){} +.s:extend(.r){} +.t:extend(.s){} + +// self referencing is ignored + +.u {color: black;} +.v.u.v:extend(.u all){} + +// circular reference because the new extend product will match the existing extend + +.w:extend(.w) {color: black;} +.v.w.v:extend(.w all){} + +// classic circular references + +.x:extend(.z) { + color: x; +} +.y:extend(.x) { + color: y; +} +.z:extend(.y) { + color: z; +} + +//very simple chaining, but with the extend inside the ruleset +.va { + color: black; +} +.vb { + &:extend(.va); + color: white; +} +.vc { + &:extend(.vb); +} + +// media queries - dont extend outside, do extend inside + +@media tv { + .ma:extend(.a,.b,.c,.d,.e,.f,.g,.h,.i,.j,.k,.l,.m,.n,.o,.p,.q,.r,.s,.t,.u,.v,.w,.x,.y,.z,.md) { + color: black; + } + .md { + color: white; + } + @media plasma { + .me, .mf { + &:extend(.mb,.md); + background: red; + } + } +} +.mb:extend(.ma) {}; +.mc:extend(.mb) {}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-clearfix.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-clearfix.less new file mode 100644 index 000000000..82445dfa5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-clearfix.less @@ -0,0 +1,19 @@ +.clearfix { + *zoom: 1; + &:after { + content: ''; + display: block; + clear: both; + height: 0; + } +} + +.foo { + &:extend(.clearfix all); + color: red; +} + +.bar { + &:extend(.clearfix all); + color: blue; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-exact.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-exact.less new file mode 100644 index 000000000..41dc41300 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-exact.less @@ -0,0 +1,46 @@ +.replace.replace, +.c.replace + .replace { + .replace, + .c { + prop: copy-paste-replace; + } +} +.rep_ace:extend(.replace.replace .replace) {} + +.a .b .c { + prop: not_effected; +} + +.a { + prop: is_effected; + .b { + prop: not_effected; + } + .b.c { + prop: not_effected; + } +} + +.c, .a { + .b, .a { + .a, .c { + prop: not_effected; + } + } +} + +.effected { + &:extend(.a); + &:extend(.b); + &:extend(.c); +} + +.e { + && { + prop: extend-double; + &:hover { + hover: not-extended; + } + } +} +.dbl:extend(.e.e) {} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-media.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-media.less new file mode 100644 index 000000000..1b22c3faf --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-media.less @@ -0,0 +1,24 @@ +.ext1 .ext2 { + background: black; +} + +@media tv { + .ext1 .ext3 { + color: white; + } + .tv-lowres :extend(.ext1 all) { + background: blue; + } + @media hires { + .ext1 .ext4 { + color: green; + } + .tv-hires :extend(.ext1 all) { + background: red; + } + } +} + +.all:extend(.ext1 all) { + +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-nest.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-nest.less new file mode 100644 index 000000000..9d4d27bbc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-nest.less @@ -0,0 +1,65 @@ +.sidebar { + width: 300px; + background: red; + + .box { + background: #FFF; + border: 1px solid #000; + margin: 10px 0; + } +} + +.sidebar2 { + &:extend(.sidebar all); + background: blue; +} + +.type1 { + .sidebar3 { + &:extend(.sidebar all); + background: green; + } +} + +.type2 { + &.sidebar4 { + &:extend(.sidebar all); + background: red; + } +} + +.button { + color: black; + &:hover { + color: white; + } +} +.submit { + &:extend(.button); + &:hover:extend(.button:hover) {} +} + +.nomatch { + &:hover:extend(.button :hover) {} +} + +.button2 { + :hover { + nested: white; + } +} +.button2 :hover { + notnested: black; +} + +.nomatch :extend(.button2:hover) {} + +.amp-test-a, +.amp-test-b { + .amp-test-c &.amp-test-d&.amp-test-e { + .amp-test-f&+&.amp-test-g:extend(.amp-test-h) {} + } +} +.amp-test-h { + test: extended by masses of selectors; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-selector.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-selector.less new file mode 100644 index 000000000..c7588ee0d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend-selector.less @@ -0,0 +1,99 @@ +.error { + border: 1px #f00; + background: #fdd; +} +.error.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error { + display: none; +} +.badError:extend(.error all) { + border-width: 3px; +} + +.foo .bar, .foo .baz { + display: none; +} + +.ext1 .ext2 + :extend(.foo all) { +} + +.ext3:extend(.foo all), +.ext4:extend(.foo all) { +} + +div.ext5, +.ext6 > .ext5 { + width: 100px; +} + +.should-not-exist-in-output, +.ext7:extend(.ext5 all) { +} + +.ext { + test: 1; +} +// same as +// .a .c:extend(.ext all) +// .b .c:extend(.ext all) +// .a .c .d +// .b .c .d +.a, .b { + test: 2; + .c:extend(.ext all) { + test: 3; + .d { + test: 4; + } + } +} + +.replace.replace, +.c.replace + .replace { + .replace, + .c { + prop: copy-paste-replace; + } +} +.rep_ace:extend(.replace all) {} + +.attributes { + [data="test"] { + extend: attributes; + } + .attribute-test { + &:extend([data="test"] all); + } + [data] { + extend: attributes2; + } + .attribute-test2 { + &:extend([data] all); //you could argue it should match [data="test"]... not for now though... + } + @attr-data: "test3"; + [data=@{attr-data}] { + extend: attributes2; + } + .attribute-test { + &:extend([data="test3"] all); + } +} + +.header { + .header-nav { + background: red; + &:before { + background: blue; + } + } +} + +.footer { + .footer-nav { + &:extend( .header .header-nav all ); + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extend.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend.less new file mode 100644 index 000000000..1db5d431d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extend.less @@ -0,0 +1,81 @@ +.error { + border: 1px #f00; + background: #fdd; +} +.error.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error { + display: none; +} +.badError { + &:extend(.error all); + border-width: 3px; +} + +.foo .bar, .foo .baz { + display: none; +} + +.ext1 .ext2 { + &:extend(.foo all); +} + +.ext3, +.ext4 { + &:extend(.foo all); + &:extend(.bar all); +} + +div.ext5, +.ext6 > .ext5 { + width: 100px; +} + +.ext7 { + &:extend(.ext5 all); +} + +.ext8.ext9 { + result: add-foo; +} +.ext8 .ext9, +.ext8 + .ext9, +.ext8 > .ext9 { + result: bar-matched; +} +.ext8.nomatch { + result: none; +} +.ext8 { + .ext9 { + result: match-nested-bar; + } +} +.ext8 { + &.ext9 { + result: match-nested-foo; + } +} + +.fuu:extend(.ext8.ext9 all) {} +.buu:extend(.ext8 .ext9 all) {} +.zap:extend(.ext8 + .ext9 all) {} +.zoo:extend(.ext8 > .ext9 all) {} + +.aa { + color: black; + .dd { + background: red; + } +} +.bb { + background: red; + .bb { + color: black; + } +} +.cc:extend(.aa,.bb) {} +.ee:extend(.dd all,.bb) {} +.ff:extend(.dd,.bb all) {} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/extract-and-length.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/extract-and-length.less new file mode 100644 index 000000000..d81e118f5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/extract-and-length.less @@ -0,0 +1,133 @@ + +// simple array/list: + +.multiunit { + @v: abc "abc" 1 1px 1% #123; + length: length(@v); + extract: extract(@v, 1) extract(@v, 2) extract(@v, 3) extract(@v, 4) extract(@v, 5) extract(@v, 6); +} + +.incorrect-index { + @v1: a b c; + @v2: a, b, c; + v1: extract(@v1, 5); + v2: extract(@v2, -2); +} + +.scalar { + @var: variable; + var-value: extract(@var, 1); + var-length: length(@var); + ill-index: extract(@var, 2); + + name-value: extract(name, 1); + string-value: extract("string", 1); + number-value: extract(12345678, 1); + color-value: extract(blue, 1); + rgba-value: extract(rgba(80, 160, 240, 0.67), 1); + empty-value: extract(~'', 1); + + name-length: length(name); + string-length: length("string"); + number-length: length(12345678); + color-length: length(blue); + rgba-length: length(rgba(80, 160, 240, 0.67)); + empty-length: length(~''); +} + +.mixin-arguments { + .mixin-args(a b c d); + .mixin-args(a, b, c, d); + .mixin-args(1; 2; 3; 4); +} + +.mixin-args(@value) { + &-1 { + length: length(@value); + extract: extract(@value, 3) ~"|" extract(@value, 2) ~"|" extract(@value, 1); + } +} + +.mixin-args(...) { + &-2 { + length: length(@arguments); + extract: extract(@arguments, 3) ~"|" extract(@arguments, 2) ~"|" extract(@arguments, 1); + } +} + +.mixin-args(@values...) { + &-3 { + length: length(@values); + extract: extract(@values, 3) ~"|" extract(@values, 2) ~"|" extract(@values, 1); + } +} + +.mixin-args(@head, @tail...) { + &-4 { + length: length(@tail); + extract: extract(@tail, 2) ~"|" extract(@tail, 1); + } +} + +// "multidimensional" array/list + +.md-space-comma { + @v: a b c, 1 2 3, "x" "y" "z"; + length-1: length(@v); + extract-1: extract(@v, 2); + length-2: length(extract(@v, 2)); + extract-2: extract(extract(@v, 2), 2); + + &-as-args {.mixin-args(a b c, 1 2 3, "x" "y" "z")} +} + +.md-cat-space-comma { + @a: a b c; + @b: 1 2 3; + @c: "x" "y" "z"; + @v: @a, @b, @c; + length-1: length(@v); + extract-1: extract(@v, 2); + length-2: length(extract(@v, 2)); + extract-2: extract(extract(@v, 2), 2); + + &-as-args {.mixin-args(@a, @b, @c)} +} + +.md-cat-comma-space { + @a: a, b, c; + @b: 1, 2, 3; + @c: "x", "y", "z"; + @v: @a @b @c; + length-1: length(@v); + extract-1: extract(@v, 2); + length-2: length(extract(@v, 2)); + extract-2: extract(extract(@v, 2), 2); + + &-as-args {.mixin-args(@a @b @c)} +} + +.md-3D { + @a: a b c d, 1 2 3 4; + @b: 5 6 7 8, e f g h; + .3D(@a, @b); + + .3D(...) { + + @v1: @arguments; + length-1: length(@v1); + extract-1: extract(@v1, 1); + + @v2: extract(@v1, 2); + length-2: length(@v2); + extract-2: extract(@v2, 1); + + @v3: extract(@v2, 1); + length-3: length(@v3); + extract-3: extract(@v3, 3); + + @v4: extract(@v3, 4); + length-4: length(@v4); + extract-4: extract(@v4, 1); + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/functions.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/functions.less new file mode 100644 index 000000000..b50a0da58 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/functions.less @@ -0,0 +1,153 @@ +#functions { + @var: 10; + @colors: #000, #fff; + color: _color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); + background: linear-gradient(@colors); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 40%); + darken: darken(#ff0000, 40%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + hsl-clamp: hsl(380, 150%, 150%); + spin-p: spin(hsl(340, 50%, 50%), 40); + spin-n: spin(hsl(30, 50%, 50%), -40); + luma-white: luma(#fff); + luma-black: luma(#000); + luma-black-alpha: luma(rgba(0,0,0,0.5)); + luma-red: luma(#ff0000); + luma-green: luma(#00ff00); + luma-blue: luma(#0000ff); + luma-yellow: luma(#ffff00); + luma-cyan: luma(#00ffff); + luma-white-alpha: luma(rgba(255,255,255,0.5)); + contrast-filter: contrast(30%); + saturate-filter: saturate(5%); + contrast-white: contrast(#fff); + contrast-black: contrast(#000); + contrast-red: contrast(#ff0000); + contrast-green: contrast(#00ff00); + contrast-blue: contrast(#0000ff); + contrast-yellow: contrast(#ffff00); + contrast-cyan: contrast(#00ffff); + contrast-light: contrast(#fff, #111111, #eeeeee); + contrast-dark: contrast(#000, #111111, #eeeeee); + contrast-wrongorder: contrast(#fff, #eeeeee, #111111, 0.5); + contrast-light-thresh: contrast(#fff, #111111, #eeeeee, 0.5); + contrast-dark-thresh: contrast(#000, #111111, #eeeeee, 0.5); + contrast-high-thresh: contrast(#555, #111111, #eeeeee, 0.6); + contrast-low-thresh: contrast(#555, #111111, #eeeeee, 0.1); + contrast-light-thresh-per: contrast(#fff, #111111, #eeeeee, 50%); + contrast-dark-thresh-per: contrast(#000, #111111, #eeeeee, 50%); + contrast-high-thresh-per: contrast(#555, #111111, #eeeeee, 60%); + contrast-low-thresh-per: contrast(#555, #111111, #eeeeee, 10%); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + format-multiple: %("hello %s %d", "earth", 2); + format-url-encode: %('red is %A', #ff0000); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); + + unitless: unit(12px); + unit: unit((13px + 1px), em); + + hue: hue(hsl(98, 12%, 95%)); + saturation: saturation(hsl(98, 12%, 95%)); + lightness: lightness(hsl(98, 12%, 95%)); + hsvhue: hsvhue(hsv(98, 12%, 95%)); + hsvsaturation: hsvsaturation(hsv(98, 12%, 95%)); + hsvvalue: hsvvalue(hsv(98, 12%, 95%)); + red: red(#f00); + green: green(#0f0); + blue: blue(#00f); + rounded: round((@r/3)); + rounded-two: round((@r/3), 2); + roundedpx: round((10px / 3)); + roundedpx-three: round((10px / 3), 3); + rounded-percentage: round(10.2%); + ceil: ceil(10.1px); + floor: floor(12.9px); + sqrt: sqrt(25px); + pi: pi(); + mod: mod(13m, 11cm); // could take into account units, doesn't at the moment + abs: abs(-4%); + tan: tan(42deg); + sin: sin(10deg); + cos: cos(12); + atan: atan(tan(0.1rad)); + atan: convert(acos(cos(34deg)), deg); + atan: convert(acos(cos(50grad)), deg); + pow: pow(8px, 2); + pow: pow(4, 3); + pow: pow(3, 3em); + min: min(0); + min: min("junk", 6, 5); + min: min(1pc, 3pt); + max: max(1, 3); + max: max(3%, 1cm, 8%, 2mm); + percentage: percentage((10px / 50)); + color: color("#ff0011"); + tint: tint(#777777, 13); + tint-full: tint(#777777, 100); + tint-percent: tint(#777777, 13%); + shade: shade(#777777, 13); + shade-full: shade(#777777, 100); + shade-percent: shade(#777777, 13%); + + fade-out: fadeOut(red, 5%); // support fadeOut and fadeout + fade-in: fadein(fadeout(red, 10%), 5%); + + hsv: hsv(5, 50%, 30%); + hsva: hsva(3, 50%, 30%, 0.2); + + mix: mix(#ff0000, #ffff00, 80); + mix-0: mix(#ff0000, #ffff00, 0); + mix-100: mix(#ff0000, #ffff00, 100); + mix-weightless: mix(#ff0000, #ffff00); + mixt: mix(#ff0000, transparent); + + .is-a { + color: iscolor(#ddd); + color1: iscolor(red); + color2: iscolor(rgb(0, 0, 0)); + color3: iscolor(transparent); + keyword: iskeyword(hello); + number: isnumber(32); + string: isstring("hello"); + pixel: ispixel(32px); + percent: ispercentage(32%); + em: isem(32em); + cat: isunit(32cat, cat); + } +} + +#alpha { + alpha: darken(hsla(25, 50%, 50%, 0.6), 10%); + alpha2: alpha(rgba(3, 4, 5, 0.5)); + alpha3: alpha(transparent); +} + +#blendmodes { + multiply: multiply(#f60000, #f60000); + screen: screen(#f60000, #0000f6); + overlay: overlay(#f60000, #0000f6); + softlight: softlight(#f60000, #ffffff); + hardlight: hardlight(#f60000, #0000f6); + difference: difference(#f60000, #0000f6); + exclusion: exclusion(#f60000, #0000f6); + average: average(#f60000, #0000f6); + negation: negation(#f60000, #313131); +} + +#extract-and-length { + @anon: A B C 1 2 3; + extract: extract(@anon, 6) extract(@anon, 5) extract(@anon, 4) extract(@anon, 3) extract(@anon, 2) extract(@anon, 1); + length: length(@anon); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/ie-filters.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/ie-filters.less new file mode 100644 index 000000000..3350b6536 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/ie-filters.less @@ -0,0 +1,15 @@ +@fat: 0; +@cloudhead: "#000000"; + +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat); +} +.evalTest(@arg) { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg); +} +.evalTest1 { + .evalTest(30); + .evalTest(5); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import-inline.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-inline.less new file mode 100644 index 000000000..95a118966 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-inline.less @@ -0,0 +1,2 @@ +@import (inline) url("import/import-test-d.css") (min-width:600px); +@import (inline, css) url("import/invalid-css.less"); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import-interpolation.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-interpolation.less new file mode 100644 index 000000000..21cfe086f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-interpolation.less @@ -0,0 +1,8 @@ +@my_theme: "test"; + +@import "import/import-@{my_theme}-e.less"; + +@import "import/import-@{in}@{terpolation}.less"; + +@in: "in"; +@terpolation: "terpolation"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import-once.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-once.less new file mode 100644 index 000000000..0a4024a38 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-once.less @@ -0,0 +1,6 @@ +@import "import/import-once-test-c"; +@import "import/import-once-test-c"; +@import "import/import-once-test-c.less"; +@import "import/deeper/import-once-test-a"; +@import (multiple) "import/import-test-f.less"; +@import (multiple) "import/import-test-f.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import-reference.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-reference.less new file mode 100644 index 000000000..cf9da168f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import-reference.less @@ -0,0 +1,18 @@ +@import (reference) url("import-once.less"); +@import (reference) url("css-3.less"); +@import (reference) url("media.less"); +/* + The media statement above is invalid (no selector) + We should ban invalid media queries with properties and no selector? +*/ +@import (reference) url("import/import-reference.less"); + +.b { + .z(); +} + +.zz(); + +.visible:extend(.z all) { + extend: test; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import.less new file mode 100644 index 000000000..016894080 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import.less @@ -0,0 +1,21 @@ +@import url(http://fonts.googleapis.com/css?family=Open+Sans); + +@import url(/absolute/something.css) screen and (color) and (max-width: 600px); + +@var: 100px; +@import url("//ha.com/file.css") (min-width:@var); + +#import-test { + .mixin; + width: 10px; + height: (@a + 10%); +} +@import "import/import-test-e" screen and (max-width: 600px); + +@import url("import/import-test-a.less"); + +@import (less, multiple) "import/import-test-d.css" screen and (max-width: 601px); + +@import (multiple) "import/import-test-e" screen and (max-width: 602px); + +@import (less, multiple) url("import/import-test-d.css") screen and (max-width: 603px); \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/deeper/import-once-test-a.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/deeper/import-once-test-a.less new file mode 100644 index 000000000..8a747fc0a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/deeper/import-once-test-a.less @@ -0,0 +1 @@ +@import "../import-once-test-c"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-and-relative-paths-test.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-and-relative-paths-test.less new file mode 100644 index 000000000..da6999896 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-and-relative-paths-test.less @@ -0,0 +1,6 @@ +@import "../css/background.css"; +@import "import-test-d.css"; + +@import "imports/logo"; +@import "imports/font"; + diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-charset-test.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-charset-test.less new file mode 100644 index 000000000..07a66e1a1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-charset-test.less @@ -0,0 +1 @@ +@charset "ISO-8859-1"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation.less new file mode 100644 index 000000000..aa49a7025 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation.less @@ -0,0 +1 @@ +@import "import-@{in}@{terpolation}2.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation2.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation2.less new file mode 100644 index 000000000..12bfb4e10 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-interpolation2.less @@ -0,0 +1,5 @@ +.a { + var: test; +} + +@in: "redefined-does-nothing"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-once-test-c.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-once-test-c.less new file mode 100644 index 000000000..686747a86 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-once-test-c.less @@ -0,0 +1,6 @@ + +@c: red; + +#import { + color: @c; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-reference.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-reference.less new file mode 100644 index 000000000..9eac45fcb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-reference.less @@ -0,0 +1,43 @@ +.z { + color: red; + .c { + color: green; + } +} +.only-with-visible, +.z { + color: green; + &:hover { + color: green; + } + & { + color: green; + } + & + & { + color: green; + .sub { + color: green; + } + } +} + +& { + .hidden { + hidden: true; + } +} + +@media tv { + .hidden { + hidden: true; + } +} + +/* comment is not output */ + +.zz { + .y { + pulled-in: yes; + } + /* comment pulled in */ +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-a.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-a.less new file mode 100644 index 000000000..b3b3b8fc8 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-a.less @@ -0,0 +1,3 @@ +@import "import-test-b.less"; +@a: 20%; +@import "urls.less"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-b.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-b.less new file mode 100644 index 000000000..ce2d35a83 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-b.less @@ -0,0 +1,8 @@ +@import "import-test-c"; + +@b: 100%; + +.mixin { + height: 10px; + color: @c; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-c.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-c.less new file mode 100644 index 000000000..686747a86 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-c.less @@ -0,0 +1,6 @@ + +@c: red; + +#import { + color: @c; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-d.css b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-d.css new file mode 100644 index 000000000..30575f018 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-d.css @@ -0,0 +1 @@ +#css { color: yellow; } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-e.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-e.less new file mode 100644 index 000000000..98b84b0a5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-e.less @@ -0,0 +1,2 @@ + +body { width: 100% } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-f.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-f.less new file mode 100644 index 000000000..fad630f9c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/import-test-f.less @@ -0,0 +1,5 @@ +@import "import-test-e"; + +.test-f { + height: 10px; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/font.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/font.less new file mode 100644 index 000000000..5abb7e769 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/font.less @@ -0,0 +1,8 @@ +@font-face { + font-family: xecret; + src: url('../assets/xecret.ttf'); +} + +#secret { + font-family: xecret, sans-serif; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/logo.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/logo.less new file mode 100644 index 000000000..22893a238 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/imports/logo.less @@ -0,0 +1,5 @@ +#logo { + width: 100px; + height: 100px; + background: url('../assets/logo.png'); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/invalid-css.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/invalid-css.less new file mode 100644 index 000000000..ed585d638 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/invalid-css.less @@ -0,0 +1 @@ +this isn't very valid CSS. \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/import/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/urls.less new file mode 100644 index 000000000..bb48f77a2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/import/urls.less @@ -0,0 +1 @@ +// empty file showing that it loads from the relative path first diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/javascript.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/javascript.less new file mode 100644 index 000000000..b826a7871 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/javascript.less @@ -0,0 +1,29 @@ +.eval { + js: `42`; + js: `1 + 1`; + js: `"hello world"`; + js: `[1, 2, 3]`; + title: `typeof process.title`; + ternary: `(1 + 1 == 2 ? true : false)`; + multiline: `(function(){var x = 1 + 1; + return x})()`; +} +.scope { + @foo: 42; + var: `parseInt(this.foo.toJS())`; + escaped: ~`2 + 5 + 'px'`; +} +.vars { + @var: `4 + 4`; + width: @var; +} +.escape-interpol { + @world: "world"; + width: ~`"hello" + " " + @{world}`; +} +.arrays { + @ary: 1, 2, 3; + @ary2: 1 2 3; + ary: `@{ary}.join(', ')`; + ary1: `@{ary2}.join(', ')`; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/lazy-eval.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/lazy-eval.less new file mode 100644 index 000000000..72b3fd46e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/lazy-eval.less @@ -0,0 +1,6 @@ +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/legacy/legacy.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/legacy/legacy.less new file mode 100644 index 000000000..92d000889 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/legacy/legacy.less @@ -0,0 +1,7 @@ +@media (-o-min-device-pixel-ratio: 2/1) { + .test-math-and-units { + font: ignores 0/0 rules; + test-division: 4 / 2 + 5em; + simple: 1px + 1px; + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/media.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/media.less new file mode 100644 index 000000000..01a6a0209 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/media.less @@ -0,0 +1,234 @@ + +// For now, variables can't be declared inside @media blocks. + +@var: 42; + +@media print { + .class { + color: blue; + .sub { + width: @var; + } + } + .top, header > h1 { + color: (#222 * 2); + } +} + +@media screen { + @base: 8; + body { max-width: (@base * 60); } +} + +@ratio_large: 16; +@ratio_small: 9; + +@media all and (device-aspect-ratio: @ratio_large / @ratio_small) { + body { max-width: 800px; } +} + +@media all and (orientation:portrait) { + aside { float: none; } +} + +@media handheld and (min-width: @var), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} + +body { + @media print { + padding: 20px; + + header { + background-color: red; + } + + @media (orientation:landscape) { + margin-left: 20px; + } + } +} + +@media screen { + .sidebar { + width: 300px; + @media (orientation: landscape) { + width: 500px; + } + } +} + +@media a { + .first { + @media b { + .second { + .third { + width: 300px; + @media c { + width: 500px; + } + } + .fourth { + width: 3; + } + } + } + } +} + +body { + @media a, b and c { + width: 95%; + + @media x, y { + width: 100%; + } + } +} + +.mediaMixin(@fallback: 200px) { + background: black; + + @media handheld { + background: white; + + @media (max-width: @fallback) { + background: red; + } + } +} + +.a { + .mediaMixin(100px); +} + +.b { + .mediaMixin(); +} +@smartphone: ~"only screen and (max-width: 200px)"; +@media @smartphone { + body { + width: 480px; + } +} + +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in; + @top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} + +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} + +.bg() { + background: red; + + @media (max-width: 500px) { + background: green; + } +} + +body { + .bg(); +} + +@bpMedium: 1000px; +@media (max-width: @bpMedium) { + body { + .bg(); + background: blue; + } +} + +@media (max-width: 1200px) { + /* a comment */ + + @media (max-width: 900px) { + body { font-size: 11px; } + } +} + +.nav-justified { + @media (min-width: 480px) { + > li { + display: table-cell; + } + } +} + +.menu +{ + @media (min-width: 768px) { + .nav-justified(); + } +} +@all: ~"all"; +@tv: ~"tv"; +@media @all and @tv { + .all-and-tv-variables { + var: all-and-tv; + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/merge.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/merge.less new file mode 100644 index 000000000..52d0796e3 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/merge.less @@ -0,0 +1,51 @@ +.first-transform() { + transform+: rotate(90deg), skew(30deg); +} +.second-transform() { + transform+: scale(2,4); +} +.third-transform() { + transform: scaleX(45deg); +} +.fourth-transform() { + transform+: scaleX(45deg); +} +.fifth-transform() { + transform+: scale(2,4) !important; +} +.first-background() { + background+: url(data://img1.png); +} +.second-background() { + background+: url(data://img2.png); +} + +.test1 { + // Can merge values + .first-transform(); + .second-transform(); +} +.test2 { + // Wont merge values without +: merge directive, for backwards compatibility with css + .first-transform(); + .third-transform(); +} +.test3 { + // Wont merge values from two sources with different properties + .fourth-transform(); + .first-background(); +} +.test4 { + // Wont merge values from sources that merked as !important, for backwards compatibility with css + .first-transform(); + .fifth-transform(); +} +.test5 { + // Wont merge values from mixins that merked as !important, for backwards compatibility with css + .first-transform(); + .second-transform() !important; +} +.test6 { + // Ignores !merge if no peers found + .second-transform(); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-args.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-args.less new file mode 100644 index 000000000..8cdc67df1 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-args.less @@ -0,0 +1,215 @@ +.mixin (@a: 1px, @b: 50%) { + width: (@a * 5); + height: (@b - 1%); +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; // asd +} + +#hidden { + .hidden; +} + +#hidden1 { + .hidden(); +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, (@var * 2)); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: (@arg1 * 2px); + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: (@glob + @a); +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } + +.mixin-arguments (@width: 0px, ...) { + border: @arguments; + width: @width; +} + +.arguments { + .mixin-arguments(1px, solid, black); +} +.arguments2 { + .mixin-arguments(); +} +.arguments3 { + .mixin-arguments; +} + +.mixin-arguments2 (@width, @rest...) { + border: @arguments; + rest: @rest; + width: @width; +} +.arguments4 { + .mixin-arguments2(0, 1, 2, 3, 4); +} + +// Edge cases + +.edge-case { + .mixin-arguments("{"); +} + +// Division vs. Literal Slash +.border-radius(@r: 2px/5px) { + border-radius: @r; +} +.slash-vs-math { + .border-radius(); + .border-radius(5px/10px); + .border-radius((3px * 2)); +} +// semi-colon vs comma for delimiting + +.mixin-takes-one(@a) { + one: @a; +} + +.mixin-takes-two(@a; @b) { + one: @a; + two: @b; +} + +.comma-vs-semi-colon { + .mixin-takes-two(@a : a; @b : b, c); + .mixin-takes-two(@a : d, e; @b : f); + .mixin-takes-one(@a: g); + .mixin-takes-one(@a : h;); + .mixin-takes-one(i); + .mixin-takes-one(j;); + .mixin-takes-two(k, l); + .mixin-takes-one(m, n;); + .mixin-takes-two(o, p; q); + .mixin-takes-two(r, s; t;); +} + +.mixin-conflict(@a:defA, @b:defB, @c:defC) { + three: @a, @b, @c; +} + +.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) { + four: @a, @b, @c, @d; +} + +#named-conflict { + .mixin-conflict(11, 12, 13, @a:a); + .mixin-conflict(@a:a, 21, 22, 23); +} +@a: 3px; +.mixin-default-arg(@a: 1px, @b: @a, @c: @b) { + defaults: 1px 1px 1px; + defaults: 2px 2px 2px; +} + +.test-mixin-default-arg { + .mixin-default-arg(); + .mixin-default-arg(2px); +} + +.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) { + margin: @margin; +} +.selector { + .mixin-comma-default1(#33acfe; 4); +} +.mixin-comma-default2(@margin: 2, 2, 2, 2;) { + margin: @margin; +} +.selector2 { + .mixin-comma-default2(); +} +.mixin-comma-default3(@margin: 2, 2, 2, 2) { + margin: @margin; +} +.selector3 { + .mixin-comma-default3(4,2,2,2); +} + +.test-calling-one-arg-mixin(@a) { +} + +.test-calling-one-arg-mixin(@a, @b, @rest...) { +} + +div { + .test-calling-one-arg-mixin(1); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-closure.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-closure.less new file mode 100644 index 000000000..01251d2ad --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-closure.less @@ -0,0 +1,26 @@ +.scope { + @var: 99px; + .mixin () { + width: @var; + } +} + +.class { + .scope > .mixin; +} + +.overwrite { + @var: 0px; + .scope > .mixin; +} + +.nested { + @var: 5px; + .mixin () { + width: @var; + } + .class { + @var: 10px; + .mixin; + } +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-guards.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-guards.less new file mode 100644 index 000000000..4d0774df0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-guards.less @@ -0,0 +1,153 @@ + +// Stacking, functions.. + +.light (@a) when (lightness(@a) > 50%) { + color: white; +} +.light (@a) when (lightness(@a) < 50%) { + color: black; +} +.light (@a) { + margin: 1px; +} + +.light1 { .light(#ddd) } +.light2 { .light(#444) } + +// Arguments against each other + +.max (@a, @b) when (@a > @b) { + width: @a; +} +.max (@a, @b) when (@a < @b) { + width: @b; +} + +.max1 { .max(3, 6) } +.max2 { .max(8, 1) } + +// Globals inside guards + +@g: auto; + +.glob (@a) when (@a = @g) { + margin: @a @g; +} +.glob1 { .glob(auto) } + +// Other operators + +.ops (@a) when (@a >= 0) { + height: gt-or-eq; +} +.ops (@a) when (@a =< 0) { + height: lt-or-eq; +} +.ops (@a) when (@a <= 0) { + height: lt-or-eq-alias; +} +.ops (@a) when not(@a = 0) { + height: not-eq; +} +.ops1 { .ops(0) } +.ops2 { .ops(1) } +.ops3 { .ops(-1) } + +// Scope and default values + +@a: auto; + +.default (@a: inherit) when (@a = inherit) { + content: default; +} +.default1 { .default } + +// true & false keywords +.test (@a) when (@a) { + content: "true."; +} +.test (@a) when not (@a) { + content: "false."; +} + +.test1 { .test(true) } +.test2 { .test(false) } +.test3 { .test(1) } +.test4 { .test(boo) } +.test5 { .test("true") } + +// Boolean expressions + +.bool () when (true) and (false) { content: true and false } // FALSE +.bool () when (true) and (true) { content: true and true } // TRUE +.bool () when (true) { content: true } // TRUE +.bool () when (false) and (false) { content: true } // FALSE +.bool () when (false), (true) { content: false, true } // TRUE +.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE +.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE +.bool () when (false), (true) and (true) { content: false, true and true } // TRUE +.bool () when (false), (false), (true) { content: false, false, true } // TRUE +.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE +.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE +.bool () when not (false) { content: not false } +.bool () when not (true) and not (false) { content: not true and not false } +.bool () when not (true) and not (true) { content: not true and not true } +.bool () when not (false) and (false), not (false) { content: not false and false, not false } + +.bool1 { .bool } + +.equality-unit-test(@num) when (@num = 1%) { + test: fail; +} +.equality-unit-test(@num) when (@num = 2) { + test: pass; +} +.equality-units { + .equality-unit-test(1px); + .equality-unit-test(2px); +} + +.colorguard(@col) when (@col = red) { content: is @col; } +.colorguard(@col) when not (blue = @col) { content: is not blue its @col; } +.colorguard(@col) {} +.colorguardtest { + .colorguard(red); + .colorguard(blue); + .colorguard(purple); +} + +.stringguard(@str) when (@str = "theme1") { content: is theme1; } +.stringguard(@str) when not ("theme2" = @str) { content: is not theme2; } +.stringguard(@str) when (~"theme1" = @str) { content: is theme1 no quotes; } +.stringguard(@str) {} +.stringguardtest { + .stringguard("theme1"); + .stringguard("theme2"); + .stringguard(theme1); +} + +.mixin(...) { + catch:all; +} +.mixin(@var) when (@var=4) { + declare: 4; +} +.mixin(@var) when (@var=4px) { + declare: 4px; +} +#tryNumberPx { + .mixin(4px); +} + +.lock-mixin(@a) { + .inner-locked-mixin(@x: @a) when (@a = 1) { + a: @a; + x: @x; + } +} +.call-lock-mixin { + .lock-mixin(1); + .call-inner-lock-mixin { + .inner-locked-mixin(); + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-important.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-important.less new file mode 100644 index 000000000..c8cc1d5ca --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-important.less @@ -0,0 +1,25 @@ +.submixin(@a) { + border-width: @a; +} +.mixin (9) { + border: 9 !important; +} +.mixin (@a: 0) { + border: @a; + boxer: @a; + .inner { + test: @a; + } + // comment + .submixin(@a); +} + +.class { + .mixin(1); + .mixin(2) !important; + .mixin(3); + .mixin(4) !important; + .mixin(5); + .mixin !important; + .mixin(9); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-named-args.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-named-args.less new file mode 100644 index 000000000..d79e0f473 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-named-args.less @@ -0,0 +1,36 @@ +.mixin (@a: 1px, @b: 50%) { + width: (@a * 5); + height: (@b - 1%); + args: @arguments; +} +.mixin (@a: 1px, @b: 50%) when (@b > 75%){ + text-align: center; +} + +.named-arg { + color: blue; + .mixin(@b: 100%); +} + +.class { + @var: 20%; + .mixin(@b: @var); +} + +.all-args-wrong-args { + .mixin(@b: 10%, @a: 2px); +} + +.mixin2 (@a: 1px, @b: 50%, @c: 50) { + width: (@a * 5); + height: (@b - 1%); + color: (#000000 + @c); +} + +.named-args2 { + .mixin2(3px, @c: 100); +} + +.named-args3 { + .mixin2(@b: 30%, @c: #123456); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-nested.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-nested.less new file mode 100644 index 000000000..43443de29 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-nested.less @@ -0,0 +1,22 @@ +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: (@a * 10); + + .innest { + width: @a; + .mix-inner((@a * 2)); + } + } +} + +.class { + .mix(30); +} + +.class2 { + .mix(60); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-pattern.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-pattern.less new file mode 100644 index 000000000..f6a12ecec --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins-pattern.less @@ -0,0 +1,99 @@ +.mixin (...) { + variadic: true; +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: (@r * 10); +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins.less new file mode 100644 index 000000000..be9e2bbde --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/mixins.less @@ -0,0 +1,141 @@ +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} + +.bo, .bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.amp { + &.support { + color: orange; + .higher { + top: 0px; + } + &.deeper { + height: auto; + } + } +} +.extended { + .bo; + .jo.ki; + .amp.support; + .amp.support.higher; + .amp.support.deeper; +} +.do .re .mi .fa { + .sol .la { + .si { + color: cyan; + } + } +} +.mutli-selector-parents { + .do.re.mi.fa.sol.la.si; +} +.foo .bar { + .bar; +} +.has_parents() { + & .underParents { + color: red; + } +} +.has_parents(); +.parent { + .has_parents(); +} +.margin_between(@above, @below) { + * + & { margin-top: @above; } + legend + & { margin-top: 0; } + & + * { margin-top: @below; } +} +h1 { .margin_between(25px, 10px); } +h2 { .margin_between(20px, 8px); } +h3 { .margin_between(15px, 5px); } + +.mixin_def(@url, @position){ + background-image: @url; + background-position: @position; +} +.error{ + @s: "/"; + .mixin_def( "@{s}a.png", center center); +} +.recursion() { + color: black; +} +.test-rec { + .recursion { + .recursion(); + } +} +.paddingFloat(@padding) { padding-left: @padding; } + +.button { + .paddingFloat(((10px + 12) * 2)); + + &.large { .paddingFloat(((10em * 2) * 2)); } +} +.clearfix() { + // ... +} +.clearfix { + .clearfix(); +} +.foo { + .clearfix(); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.less new file mode 100644 index 000000000..15ef8a456 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.less @@ -0,0 +1,3 @@ +.a { + a: `1 + 1`; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.txt b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.txt new file mode 100644 index 000000000..d81dd2bdb --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-js-errors/no-js-errors.txt @@ -0,0 +1,4 @@ +SyntaxError: You are using JavaScript, which has been disabled. in {path}no-js-errors.less on line 2, column 6: +1 .a { +2 a: `1 + 1`; +3 } diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/no-output.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-output.less new file mode 100644 index 000000000..1db074565 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/no-output.less @@ -0,0 +1,2 @@ +.mixin() { +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/operations.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/operations.less new file mode 100644 index 000000000..3e483c8b6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/operations.less @@ -0,0 +1,62 @@ +#operations { + color: (#110000 + #000011 + #001100); // #111111 + height: (10px / 2px + 6px - 1px * 2); // 9px + width: (2 * 4 - 5em); // 3em + .spacing { + height: (10px / 2px+6px-1px*2); + width: (2 * 4-5em); + } + substraction: (20 - 10 - 5 - 5); // 0 + division: (20 / 5 / 4); // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: (@x + @y); // 16em + width: (12 + @y); // 24em + size: (5cm - @x); // 1cm +} + +.with-functions { + color: (rgb(200, 200, 200) / 2); + color: (2 * hsl(0, 50%, 50%)); + color: (rgb(10, 10, 10) + hsl(0, 50%, 50%)); +} + +@z: -2; + +.negative { + height: (2px + @z); // 0px + width: (2px - @z); // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.rem-dimensions { + font-size: (20rem / 5 + 1.5rem); // 5.5rem +} + +.colors { + color: #123; // #112233 + border-color: (#234 + #111111); // #334455 + background-color: (#222222 - #fff); // #000000 + .other { + color: (2 * #111); // #222222 + border-color: (#333333 / 3 + #111); // #222222 + } +} + +.negations { + @var: 4px; + variable: (-@var); // 4 + variable1: (-@var + @var); // 0 + variable2: (@var + -@var); // 0 + variable3: (@var - -@var); // 8 + variable4: (-@var - -@var); // 0 + paren: (-(@var)); // -4px + paren2: (-(2 + 2) * -@var); // 16 +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/parens.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/parens.less new file mode 100644 index 000000000..deb413919 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/parens.less @@ -0,0 +1,41 @@ +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6 * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width-all: ((@var * @var) * 6); + width-first: ((@var * @var)) * 6; + width-keep: (@var * @var) * 6; + height-keep: (7 * 7) + (8 * 8); + height-all: ((7 * 7) + (8 * 8)); + height-parts: ((7 * 7)) + ((8 * 8)); + margin-keep: (4 * (5 + 5) / 2) - (@var * 2); + margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2)); + margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2))); + border-radius-keep: 4px * (1 + 1) / @var + 3px; + border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px)); + border-radius-all: (4px * (1 + 1) / @var + 3px); + //margin: (6 * 6)px; +} + +.negative { + @var: 1; + neg-var: -@var; // -1 ? + neg-var-paren: -(@var); // -(1) ? +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/rulesets.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/rulesets.less new file mode 100644 index 000000000..e81192dbc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/rulesets.less @@ -0,0 +1,30 @@ +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/scope.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/scope.less new file mode 100644 index 000000000..36d37061c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/scope.less @@ -0,0 +1,79 @@ +@x: red; +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} +@mix: blue; +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +} + +#namespace { + .scoped_mixin() { + @local-will-be-made-global: green; + .scope { + scoped-val: @local-will-be-made-global; + } + } +} + +#namespace > .scoped_mixin(); + +.setHeight(@h) { @height: 1024px; } +.useHeightInMixinCall(@h) { .useHeightInMixinCall { mixin-height: @h; } } +@mainHeight: 50%; +.setHeight(@mainHeight); +.heightIsSet { height: @height; } +.useHeightInMixinCall(@height); + +.importRuleset() { + .imported { + exists: true; + } +} +.importRuleset(); +.testImported { + .imported; +} + +@parameterDefault: 'top level'; +@anotherVariable: 'top level'; +//mixin uses top-level variables +.mixinNoParam(@parameter: @parameterDefault) when (@parameter = 'top level') { + default: @parameter; + scope: @anotherVariable; + sub-scope-only: @subScopeOnly; +} + +#allAreUsedHere { + //redefine top-level variables in different scope + @parameterDefault: 'inside'; + @anotherVariable: 'inside'; + @subScopeOnly: 'inside'; + //use the mixin + .mixinNoParam(); +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/selectors.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/selectors.less new file mode 100644 index 000000000..ed7db7ce0 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/selectors.less @@ -0,0 +1,144 @@ +h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} + +a { + color: red; + + &:hover { color: blue; } + + div & { color: green; } + + p & span { color: yellow; } +} + +.foo { + .bar, .baz { + & .qux { + display: block; + } + .qux & { + display: inline; + } + .qux& { + display: inline-block; + } + .qux & .biz { + display: none; + } + } +} + +.b { + &.c { + .a& { + color: red; + } + } +} + +.b { + .c & { + &.a { + color: red; + } + } +} + +.p { + .foo &.bar { + color: red; + } +} + +.p { + .foo&.bar { + color: red; + } +} + +.foo { + .foo + & { + background: amber; + } + & + & { + background: amber; + } +} + +.foo, .bar { + & + & { + background: amber; + } +} + +.foo, .bar { + a, b { + & > & { + background: amber; + } + } +} + +.other ::fnord { color: red } +.other::fnord { color: red } +.other { + ::bnord {color: red } + &::bnord {color: red } +} +// selector interpolation +@theme: blood; +@selector: ~".@{theme}"; +@{selector} { + color:red; +} +@{selector}red { + color: green; +} +.red { + #@{theme}.@{theme}&.black { + color:black; + } +} +@num: 3; +:nth-child(@{num}) { + selector: interpolated; +} +.test { + &:nth-child(odd):not(:nth-child(3)) { + color: #ff0000; + } +} +[prop], +[prop=10%], +[prop="value@{num}"], +[prop*="val@{num}"], +[|prop~="val@{num}"], +[*|prop$="val@{num}"], +[ns|prop^="val@{num}"], +[@{num}^="val@{num}"], +[@{num}=@{num}], +[@{num}] { + attributes: yes; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/basic.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/basic.less new file mode 100644 index 000000000..4ee8b4f6d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/basic.less @@ -0,0 +1,27 @@ +@var: black; + +.a() { + color: red; +} + +.b { + color: green; + .a(); + color: blue; + background: @var; +} + +.a, .b { + background: green; + .c, .d { + background: gray; + & + & { + color: red; + } + } +} + +.extend:extend(.a all) { + color: pink; +} +@import (inline) "imported.css"; \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/imported.css b/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/imported.css new file mode 100644 index 000000000..0fc365706 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/sourcemaps/imported.css @@ -0,0 +1,7 @@ +/*comments*/ +.unused-css { + color: white; +} +.imported { + color: black; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/static-urls/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/static-urls/urls.less new file mode 100644 index 000000000..b0c7de09a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/static-urls/urls.less @@ -0,0 +1,33 @@ +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} + +@import "../import/import-and-relative-paths-test"; diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/strings.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/strings.less new file mode 100644 index 000000000..c43e368dd --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/strings.less @@ -0,0 +1,57 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: ~"DX.Transform.MS.BS.filter(opacity=50)"; +} +#one-line { image: url(http://tooks.com) } +#crazy { image: url(http://), "}", url("http://}") } +#interpolation { + @var: '/dev'; + url: "http://lesscss.org@{var}/image.jpg"; + + @var2: 256; + url2: "http://lesscss.org/image-@{var2}.jpg"; + + @var3: #456; + url3: "http://lesscss.org@{var3}"; + + @var4: hello; + url4: "http://lesscss.org/@{var4}"; + + @var5: 54.4px; + url5: "http://lesscss.org/@{var5}"; +} + +// multiple calls with string interpolation + +.mix-mul (@a: green) { + color: ~"@{a}"; +} +.mix-mul-class { + .mix-mul(blue); + .mix-mul(red); + .mix-mul(black); + .mix-mul(orange); +} + +@test: Arial, Verdana, San-Serif; +.watermark { + @family: ~"Univers, @{test}"; + family: @family; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/urls.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/urls.less new file mode 100644 index 000000000..5ef87635a --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/urls.less @@ -0,0 +1,67 @@ +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; + background: url("img.jpg") center / 100px; + background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); + background-image: url("http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700"); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} + +@import "import/import-and-relative-paths-test"; + +#data-uri { + uri: data-uri('image/jpeg;base64', '../data/image.jpg'); +} + +#data-uri-guess { + uri: data-uri('../data/image.jpg'); +} + +#data-uri-ascii { + uri-1: data-uri('text/html', '../data/page.html'); + uri-2: data-uri('../data/page.html'); +} + +#data-uri-toobig { + uri: data-uri('../data/data-uri-fail.png'); +} +.add_an_import(@file_to_import) { +@import "@{file_to_import}"; +} + +.add_an_import("file.css"); + +#svg-functions { + background-image: svg-gradient(to bottom, black, white); + background-image: svg-gradient(to bottom, black, orange 3%, white); + @green_5: green 5%; + @orange_percentage: 3%; + @orange_color: orange; + background-image: svg-gradient(to bottom, (mix(black, white) + #444) 1%, @orange_color @orange_percentage, ((@green_5)), white 95%); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/variables.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/variables.less new file mode 100644 index 000000000..e896f4049 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/variables.less @@ -0,0 +1,83 @@ +@a: 2; +@x: (@a * @a); +@y: (@x + 1); +@z: (@x * 2 + @y); +@var: -1; + +.variables { + width: (@z + 1cm); // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; +@onePixel: 1px; + +.variables { + height: (@b + @x + 0px); // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redef { + @var: 0; + .inition { + @var: 4; + @var: 2; + three: @var; + @var: 3; + } + zero: @var; +} + +.values { + minus-one: @var; + @a: 'Trebuchet'; + @multi: 'A', B, C; + font-family: @a, @a, @a; + color: @c !important; + multi: something @multi, @a; +} + +.variable-names { + @var: 'hello'; + @name: 'var'; + name: @@name; +} + +.alpha { + @var: 42; + filter: alpha(opacity=@var); +} + +.polluteMixin() { + @a: 'pollution'; +} +.testPollution { + @a: 'no-pollution'; + a: @a; + .polluteMixin(); + a: @a; +} + +.units { + width: @onePixel; + same-unit-as-previously: (@onePixel / @onePixel); + square-pixel-divided: (@onePixel * @onePixel / @onePixel); + odd-unit: unit((@onePixel * 4em / 2cm)); + percentage: (10 * 50%); + pixels: (50px * 10); + conversion-metric-a: (20mm + 1cm); + conversion-metric-b: (1cm + 20mm); + conversion-imperial: (1in + 72pt + 6pc); + custom-unit: (42octocats * 10); + custom-unit-cancelling: (8cats * 9dogs / 4cats); + mix-units: (1px + 1em); + invalid-units: (1px * 1px); +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/less/whitespace.less b/node_modules/grunt-contrib-less/node_modules/less/test/less/whitespace.less new file mode 100644 index 000000000..ab4804da9 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/less/whitespace.less @@ -0,0 +1,44 @@ + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +.sel +.newline_ws .tab_ws { +color: +white; +background-position: 45 +-23; +} diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/basic.json b/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/basic.json new file mode 100644 index 000000000..9018fef9c --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/basic.json @@ -0,0 +1 @@ +{"version":3,"file":"sourcemaps/basic.css","sources":["testweb/sourcemaps/imported.css","testweb/sourcemaps/basic.less"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;ACAG;EACD,YAAA;EAJA,UAAA;EAWA,iBAAA;EALA,WAAA;EACA,mBAAA;;AAJC,EASC;AATD,EASM;EACL,gBAAA;;AACE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;EAGH,UAAA;;AALJ;AAAK;AAUA;EATL,iBAAA;;AADA,EAEE;AAFG,EAEH;AAFF,EAEO;AAFF,EAEE;AAQF,OARH;AAQG,OARE;EACL,gBAAA;;AACE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFD;AAQF,OARH,GAQG,UARH;AAQG,OARH,GAEM,KAFN;AAQG,OARH,GAQG,UARE;AAQF,OARH,GAEM,KAFD;AAEH,EAFF,GAQG,UARH;AAEE,EAFF,GAQG,UARE;AAQF,OARE,GAQF,UARH;AAQG,OARE,GAEC,KAFN;AAQG,OARE,GAQF,UARE;AAQF,OARE,GAEC,KAFD;AAEH,EAFG,GAQF,UARH;AAEE,EAFG,GAQF,UARE;EAGH,UAAA;;AAKC;EACL,WAAA"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/index.html b/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/index.html new file mode 100644 index 000000000..89acca77e --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/test/sourcemaps/index.html @@ -0,0 +1,17 @@ + + + + + + +
    id import-test
    +
    id import-test
    +
    class imported inline
    +
    class mixin
    +
    class a
    +
    class b
    +
    class b
    class c
    +
    class a
    class d
    +
    class extend
    class c
    + + \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-browser.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-browser.html new file mode 100644 index 000000000..269235ca2 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-browser.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-errors.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-errors.html new file mode 100644 index 000000000..1b38879b4 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-errors.html @@ -0,0 +1,195 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-global-vars.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-global-vars.html new file mode 100644 index 000000000..55ee41615 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-global-vars.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-legacy.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-legacy.html new file mode 100644 index 000000000..0450416cc --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-legacy.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-main.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-main.html new file mode 100644 index 000000000..f316cb48d --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-main.html @@ -0,0 +1,223 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-modify-vars.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-modify-vars.html new file mode 100644 index 000000000..6933eff60 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-modify-vars.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-no-js-errors.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-no-js-errors.html new file mode 100644 index 000000000..b7a2cf1d5 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-no-js-errors.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-production.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-production.html new file mode 100644 index 000000000..c535435d6 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-production.html @@ -0,0 +1,55 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-relative-urls.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-relative-urls.html new file mode 100644 index 000000000..cb54a4d1f --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-relative-urls.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath-relative.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath-relative.html new file mode 100644 index 000000000..ceae2e555 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath-relative.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath.html b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath.html new file mode 100644 index 000000000..5a0db6736 --- /dev/null +++ b/node_modules/grunt-contrib-less/node_modules/less/tmp/browser/test-runner-rootpath.html @@ -0,0 +1,59 @@ + + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/grunt-contrib-less/package.json b/node_modules/grunt-contrib-less/package.json new file mode 100644 index 000000000..680a3a593 --- /dev/null +++ b/node_modules/grunt-contrib-less/package.json @@ -0,0 +1,92 @@ +{ + "name": "grunt-contrib-less", + "description": "Compile LESS files to CSS.", + "version": "0.8.2", + "homepage": "https://github.com/gruntjs/grunt-contrib-less", + "author": { + "name": "Grunt Team", + "url": "http://gruntjs.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/gruntjs/grunt-contrib-less.git" + }, + "bugs": { + "url": "https://github.com/gruntjs/grunt-contrib-less/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/gruntjs/grunt-contrib-less/blob/master/LICENSE-MIT" + } + ], + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "less": "~1.5.0", + "grunt-lib-contrib": "~0.6.1" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.6.2", + "grunt-contrib-nodeunit": "~0.2.0", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-internal": "~0.4.5", + "grunt": "~0.4.0" + }, + "peerDependencies": { + "grunt": "~0.4.0" + }, + "keywords": [ + "gruntplugin" + ], + "contributors": [ + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com/" + }, + { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + { + "name": "Chris Talkington", + "url": "http://christalkington.com/" + }, + { + "name": "Teddy Cross", + "url": "http://tkaz.ec/" + }, + { + "name": "Justin Searls", + "url": "http://about.me/searls/" + }, + { + "name": "Thomas Boyt", + "url": "http://www.thomasboyt.com/" + }, + { + "name": "Jake Harding", + "url": "http://thejakeharding.com/" + }, + { + "name": "Jason Karns", + "url": "http://jasonkarns.com/" + }, + { + "name": "Sebastian Tschan", + "url": "https://blueimp.net/" + } + ], + "readme": "# grunt-contrib-less v0.8.2 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-less.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-less)\n\n> Compile LESS files to CSS.\n\n\n\n## Getting Started\nThis plugin requires Grunt `~0.4.0`\n\nIf you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:\n\n```shell\nnpm install grunt-contrib-less --save-dev\n```\n\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\n\n```js\ngrunt.loadNpmTasks('grunt-contrib-less');\n```\n\n*This plugin was designed to work with Grunt 0.4.x. If you're still using grunt v0.3.x it's strongly recommended that [you upgrade](http://gruntjs.com/upgrading-from-0.3-to-0.4), but in case you can't please use [v0.3.2](https://github.com/gruntjs/grunt-contrib-less/tree/grunt-0.3-stable).*\n\n\n## Less task\n_Run this task with the `grunt less` command._\n\nTask targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide.\n### Options\n\n#### paths\nType: `String|Array`\nDefault: Directory of input file.\n\nSpecifies directories to scan for @import directives when parsing. Default value is the directory of the source, which is probably what you want.\n\n#### compress\nType: `Boolean`\nDefault: `false`\n\nCompress output by removing some whitespaces.\n\n#### cleancss\nType: `Boolean`\nDefault: `false`\n\nCompress output using [clean-css](https://npmjs.org/package/clean-css).\n\n#### ieCompat\nType: `Boolean`\nDefault: `true`\n\nEnforce the css output is compatible with Internet Explorer 8.\n\nFor example, the [data-uri](https://github.com/cloudhead/less.js/pull/1086) function encodes a file in base64 encoding and embeds it into the generated CSS files as a data-URI. Because Internet Explorer 8 limits `data-uri`s to 32KB, the [ieCompat](https://github.com/cloudhead/less.js/pull/1190) option prevents `less` from exceeding this.\n\n#### optimization\nType: `Integer`\nDefault: `null`\n\nSet the parser's optimization level. The lower the number, the less nodes it will create in the tree. This could matter for debugging, or if you want to access the individual nodes in the tree.\n\n#### strictImports\nType: `Boolean`\nDefault: `false`\n\nForce evaluation of imports.\n\n#### strictMath\nType: `Boolean`\nDefault: `false`\n\nWhen enabled, math is required to be in parenthesis.\n\n#### strictUnits\nType: `Boolean`\nDefault: `false`\n\nWhen enabled, less will validate the units used (e.g. 4px/2px = 2, not 2px and 4em/2px throws an error).\n\n#### syncImport\nType: `Boolean`\nDefault: `false`\n\nRead @import'ed files synchronously from disk.\n\n#### dumpLineNumbers\nType: `String`\nDefault: `false`\n\nConfigures -sass-debug-info support.\n\nAccepts following values: `comments`, `mediaquery`, `all`.\n\n#### relativeUrls\nType: `Boolean`\nDefault: `false`\n\nRewrite urls to be relative. false: do not modify urls.\n\n#### customFunctions\nType: `Object`\nDefault: none\n\nDefine custom functions to be available within your LESS stylesheets. The function's name must be lowercase and\nreturn a primitive type (not an object or array). In the function definition, the first argument is the less\nobject, and subsequent arguments are from the less function call. Values passed to the function are not simple\nprimitive types, rather types defined within less. See the LESS documentation for more information on the available types.\n\n#### report\nChoices: `false` `'min'` `'gzip'`\nDefault: `false`\n\nEither do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Less is performing, but using `'gzip'` can add 5-10x runtime task execution.\n\nExample ouput using `'gzip'`:\n\n```\nOriginal: 198444 bytes.\nMinified: 101615 bytes.\nGzipped: 20084 bytes.\n```\n\n#### sourceMap\nType: `Boolean`\nDefault: `false`\n\nEnable source maps.\n\n#### sourceMapFilename\nType: `String`\nDefault: none\n\nWrite the source map to a separate file with the given filename.\n\n#### sourceMapBasepath\nType: `String`\nDefault: none\n\nSets the base path for the less file paths in the source map.\n\n#### sourceMapRootpath\nType: `String`\nDefault: none\n\nAdds this path onto the less file paths in the source map.\n\n#### outputSourceFiles\nType: `Boolean`\nDefault: false\n\nPuts the less files into the map instead of referencing them.\n\n### Usage Examples\n\n```js\nless: {\n development: {\n options: {\n paths: [\"assets/css\"]\n },\n files: {\n \"path/to/result.css\": \"path/to/source.less\"\n }\n },\n production: {\n options: {\n paths: [\"assets/css\"],\n cleancss: true\n },\n files: {\n \"path/to/result.css\": \"path/to/source.less\"\n }\n }\n}\n```\n\n\n## Release History\n\n * 2013-11-14   v0.8.2   Support outputSourceFiles\n * 2013-10-24   v0.8.1   Support sourceMapFilename, sourceMapBasepath and sourceMapRootpath\n * 2013-10-22   v0.8.0   Upgrade to LESS 1.5 Support strictUnits option Support sourceMap option Add customFunctions option for defining custom functions within LESS Output the source file name on error yuicompress option now cleancss (Less changed underlying dependency)\n * 2013-08-08   v0.7.0   Downgrade no source files warning to only in verbose mode\n * 2013-08-08   v0.6.5   Support strictMath option Support rootpath parse option\n * 2013-07-09   v0.6.4   Support relativeUrls option\n * 2013-07-06   v0.6.3   Add report option for minification and gzip results\n * 2013-07-03   v0.6.2   support syncImport\n * 2013-06-12   v0.6.1   Support ieCompat\n * 2013-06-09   v0.6.0   Bump less to 1.4.0\n * 2013-05-23   v0.5.2   Improve error handling.\n * 2013-04-25   v0.5.1   Gracefully handle configuration without sources.\n * 2013-02-15   v0.5.0   First official release for Grunt 0.4.0.\n * 2013-01-23   v0.5.0rc7   Updating grunt/gruntplugin dependencies to rc7. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. Remove experimental wildcard destination support. Switching to this.files api.\n * 2012-10-18   v0.3.2   Add support for dumpLineNumbers.\n * 2012-10-12   v0.3.1   Rename grunt-contrib-lib dep to grunt-lib-contrib.\n * 2012-09-24   v0.3.0   Global options depreciated Revert normalize linefeeds.\n * 2012-09-16   v0.2.2   Support all less options Normalize linefeeds Default path to dirname of src file.\n * 2012-09-10   v0.2.0   Refactored from grunt-contrib into individual repo.\n\n---\n\nTask submitted by [Tyler Kellen](http://goingslowly.com/)\n\n*This file was generated on Thu Nov 14 2013 09:29:34.*\n", + "readmeFilename": "README.md", + "_id": "grunt-contrib-less@0.8.2", + "dist": { + "shasum": "9adc5f10571153fe1541d83f73ba734ff84de09a" + }, + "_from": "grunt-contrib-less@~0.8.1", + "_resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-0.8.2.tgz" +} diff --git a/node_modules/grunt-contrib-less/tasks/less.js b/node_modules/grunt-contrib-less/tasks/less.js new file mode 100644 index 000000000..293926d89 --- /dev/null +++ b/node_modules/grunt-contrib-less/tasks/less.js @@ -0,0 +1,155 @@ +/* + * grunt-contrib-less + * http://gruntjs.com/ + * + * Copyright (c) 2013 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Internal lib. + var contrib = require('grunt-lib-contrib').init(grunt); + + var path = require('path'); + var less = require('less'); + + var lessOptions = { + parse: ['paths', 'optimization', 'filename', 'strictImports', 'syncImport', 'dumpLineNumbers', 'relativeUrls', 'rootpath'], + render: ['compress', 'cleancss', 'ieCompat', 'strictMath', 'strictUnits', + 'sourceMap', 'sourceMapFilename', 'sourceMapBasepath', 'sourceMapRootpath', 'outputSourceFiles'] + }; + + grunt.registerMultiTask('less', 'Compile LESS files to CSS', function() { + var done = this.async(); + + var options = this.options(); + grunt.verbose.writeflags(options, 'Options'); + + if (this.files.length < 1) { + grunt.verbose.warn('Destination not written because no source files were provided.'); + } + + grunt.util.async.forEachSeries(this.files, function(f, nextFileObj) { + var destFile = f.dest; + + var files = f.src.filter(function(filepath) { + // Warn on and remove invalid source files (if nonull was set). + if (!grunt.file.exists(filepath)) { + grunt.log.warn('Source file "' + filepath + '" not found.'); + return false; + } else { + return true; + } + }); + + if (files.length === 0) { + if (f.src.length < 1) { + grunt.log.warn('Destination not written because no source files were found.'); + } + + // No src files, goto next target. Warn would have been issued above. + return nextFileObj(); + } + + var compiledMax = [], compiledMin = []; + grunt.util.async.concatSeries(files, function(file, next) { + compileLess(file, options, function(css, err) { + if (!err) { + if (css.max) { + compiledMax.push(css.max); + } + compiledMin.push(css.min); + next(); + } else { + nextFileObj(err); + } + }, function (sourceMapContent) { + grunt.file.write(options.sourceMapFilename, sourceMapContent); + grunt.log.writeln('File ' + options.sourceMapFilename.cyan + ' created.'); + }); + }, function() { + if (compiledMin.length < 1) { + grunt.log.warn('Destination not written because compiled files were empty.'); + } else { + var min = compiledMin.join(options.cleancss ? '' : grunt.util.normalizelf(grunt.util.linefeed)); + grunt.file.write(destFile, min); + grunt.log.writeln('File ' + destFile.cyan + ' created.'); + + // ...and report some size information. + if (options.report) { + contrib.minMaxInfo(min, compiledMax.join(grunt.util.normalizelf(grunt.util.linefeed)), options.report); + } + } + nextFileObj(); + }); + + }, done); + }); + + var compileLess = function(srcFile, options, callback, sourceMapCallback) { + options = grunt.util._.extend({filename: srcFile}, options); + options.paths = options.paths || [path.dirname(srcFile)]; + + var css; + var srcCode = grunt.file.read(srcFile); + + var parser = new less.Parser(grunt.util._.pick(options, lessOptions.parse)); + + parser.parse(srcCode, function(parse_err, tree) { + if (parse_err) { + lessError(parse_err, srcFile); + callback('',true); + } + + // Load custom functions + if (options.customFunctions) { + Object.keys(options.customFunctions).forEach(function(name) { + less.tree.functions[name.toLowerCase()] = function() { + var args = [].slice.call(arguments); + args.unshift(less); + return new less.tree.Anonymous(options.customFunctions[name].apply(this, args)); + }; + }); + } + + var minifyOptions = grunt.util._.pick(options, lessOptions.render); + + if (minifyOptions.sourceMapFilename) { + minifyOptions.writeSourceMap = sourceMapCallback; + } + + try { + css = minify(tree, minifyOptions); + callback(css, null); + } catch (e) { + lessError(e, srcFile); + callback(css, true); + } + }); + }; + + var formatLessError = function(e) { + var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']'; + return e.filename + ': ' + pos + ' ' + e.message; + }; + + var lessError = function(e, file) { + var message = less.formatError ? less.formatError(e) : formatLessError(e); + + grunt.log.error(message); + grunt.fail.warn('Error compiling ' + file); + }; + + var minify = function (tree, options) { + var result = { + min: tree.toCSS(options) + }; + if (!grunt.util._.isEmpty(options)) { + result.max = tree.toCSS(); + } + return result; + }; +}; diff --git a/node_modules/grunt-contrib-less/test/expected/cleancss.css b/node_modules/grunt-contrib-less/test/expected/cleancss.css new file mode 100644 index 000000000..2a6eb0de4 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/cleancss.css @@ -0,0 +1 @@ +body{color:#fff} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/test/expected/cleancssReport.css b/node_modules/grunt-contrib-less/test/expected/cleancssReport.css new file mode 100644 index 000000000..4a152bd59 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/cleancssReport.css @@ -0,0 +1 @@ +body{color:#fff}#header{background:#fff}#footer{color:#377;background:#233} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/test/expected/compress.css b/node_modules/grunt-contrib-less/test/expected/compress.css new file mode 100644 index 000000000..2a6eb0de4 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/compress.css @@ -0,0 +1 @@ +body{color:#fff} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/test/expected/concat.css b/node_modules/grunt-contrib-less/test/expected/concat.css new file mode 100644 index 000000000..a1f1d2a72 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/concat.css @@ -0,0 +1,12 @@ +body { + color: #ffffff; +} + +#header { + background: #ffffff; +} + +#footer { + color: #377; + background: #233; +} diff --git a/node_modules/grunt-contrib-less/test/expected/customFunctions.css b/node_modules/grunt-contrib-less/test/expected/customFunctions.css new file mode 100644 index 000000000..cd9882545 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/customFunctions.css @@ -0,0 +1,5 @@ +.myRule { + background-color: red; + width: 5px; + background: "Hello"; +} diff --git a/node_modules/grunt-contrib-less/test/expected/ieCompatFalse.css b/node_modules/grunt-contrib-less/test/expected/ieCompatFalse.css new file mode 100644 index 000000000..6dfad771c --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/ieCompatFalse.css @@ -0,0 +1,5 @@ +body { + width: 288px; + height: 288px; + background: transparent url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAwADAAD/7RtYUGhvdG9zaG9wIDMuMAA4QklNBCUAAAAAABAAAAAAAAAAAAAAAAAAAAAAOEJJTQPtAAAAAAAQAAMAAAABAAEAAwAAAAEAAThCSU0EJgAAAAAADgAAAAAAAAAAAAA/gAAAOEJJTQQNAAAAAAAEAAAAHjhCSU0EGQAAAAAABAAAAB44QklNA/MAAAAAAAkAAAAAAAAAAAEAOEJJTQQKAAAAAAABAAA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAANlAAAABgAAAAAAAAAAAAACKAAABAAAAAAYAEgAYQBwAHAAeQAtAEcAaQBsAG0AbwByAGUALQBCAG8AYgAtAEIAYQByAGsAZQByAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAQAAAACKAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAbnVsbAAAAAIAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAACKAAAAABSZ2h0bG9uZwAABAAAAAAGc2xpY2VzVmxMcwAAAAFPYmpjAAAAAQAAAAAABXNsaWNlAAAAEgAAAAdzbGljZUlEbG9uZwAAAAAAAAAHZ3JvdXBJRGxvbmcAAAAAAAAABm9yaWdpbmVudW0AAAAMRVNsaWNlT3JpZ2luAAAADWF1dG9HZW5lcmF0ZWQAAAAAVHlwZWVudW0AAAAKRVNsaWNlVHlwZQAAAABJbWcgAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAigAAAAAUmdodGxvbmcAAAQAAAAAA3VybFRFWFQAAAABAAAAAAAAbnVsbFRFWFQAAAABAAAAAAAATXNnZVRFWFQAAAABAAAAAAAGYWx0VGFnVEVYVAAAAAEAAAAAAA5jZWxsVGV4dElzSFRNTGJvb2wBAAAACGNlbGxUZXh0VEVYVAAAAAEAAAAAAAlob3J6QWxpZ25lbnVtAAAAD0VTbGljZUhvcnpBbGlnbgAAAAdkZWZhdWx0AAAACXZlcnRBbGlnbmVudW0AAAAPRVNsaWNlVmVydEFsaWduAAAAB2RlZmF1bHQAAAALYmdDb2xvclR5cGVlbnVtAAAAEUVTbGljZUJHQ29sb3JUeXBlAAAAAE5vbmUAAAAJdG9wT3V0c2V0bG9uZwAAAAAAAAAKbGVmdE91dHNldGxvbmcAAAAAAAAADGJvdHRvbU91dHNldGxvbmcAAAAAAAAAC3JpZ2h0T3V0c2V0bG9uZwAAAAAAOEJJTQQoAAAAAAAMAAAAAT/wAAAAAAAAOEJJTQQRAAAAAAABAQA4QklNBBQAAAAAAAQAAAABOEJJTQQMAAAAABV2AAAAAQAAAKAAAABWAAAB4AAAoUAAABVaABgAAf/Y/+AAEEpGSUYAAQIAAEgASAAA/+0ADEFkb2JlX0NNAAL/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsKCxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0ODRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABWAKADASIAAhEBAxEB/90ABAAK/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQFBgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhEDBCESMQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwclklPw4fFjczUWorKDJkSTVGRFwqN0NhfSVeJl8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2N0dXZ3eHl6e3x9fn9xEAAgIBAgQEAwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR8DMkYuFygpJDUxVjczTxJQYWorKDByY1wtJEk1SjF2RFVTZ0ZeLys4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9ic3R1dnd4eXp7fH/9oADAMBAAIRAxEAPwDhA5wcySTtMFrBMh30jDB+d/o/oKDGOBG4OJGs88naNw+juSZWJO4kMGsHvI/6j+SxGDmAB0e46kmIbp7fZ/wkO/lqrbAwe5r+QRHLwSNPzNzT7XbdqZ0VtYWFu0zqwE6jx/N3+1TJr9N7SQQDtBBlskuLtrY/cb9BDADm+mGhoME7SCTxo1v8hv5n0K0gmtWVbn2n0wN7n6BnumdHy4/nLf6d9Us6+H5J+xMHAeA97pl383ub6f8AbT/VammtwypL7QSGtHtDP62rv0n/AFC38nqeUbiK9Gx4DX4uTuGIHFL7F+PEZmgN0WL9UOiUDdc+zJdEQYY0Dwir+Uqeb0Hppa6vFcaHgfoxuLqjHDHiXOZ/rv8AUWm2qy4zkX2OPIaw7W/9GE1uJX9L3OJ5cef7WiZLND91tx5E1rIPD30X12+jbWWkn3AxJ/qun+V/UQSwEASNonUS4aj3a/nbI/d9i6nqGBTkU2Y72huQ0bsZ4HO2dzHf1m/TXLl9Xqmt4DbmnQPkatPP57UhRAMdi1cuKUJmMh/LuxLHbTZWxrondYIJ+jw5v7iTNdrmEEc7uw0MxI3e76aMwgje7aRrBcQIAP5p2e/0nfvIVjC8+3RzCXBh9oP8nZq33f8ATSYqVL9HOcS0kkWNO6D/ACt3uc9TrbawbmkNAjc4aNP8rj/OYo1bgNuxp9sbZgNjzcPamDdkWBgAd7W943a7Hf12+39L+Yh3Toka2lxB3Fp/OAMOLeQ4afR9qdoeJAHYH3ENcJ7jT6CFWXu9hiGjQwIAn28f6/8ACKYNdYLXOAkmQdW/12au2/8Age9Ajokyl9irfc/Y+Ghw2u1IM/yfzX/9WnNLq3B4dteIEaAmBt7fvJq7g1pD9tjCJDYka/vbh9H+qiNDwW+mdvltkOb/ACP3NiWyhuvW0NbLiS4HaWETx5O3Oa7Yk7R5DS5r38mJa5Qe5u0taXhnE6Brf+DrcfpJbmVsIJPaQNOeNhCGqC//0OB3iQ5rhJgsDx/aj81m5n0U5DnPL/osMxt5/r7S7c76KcWBnvbWATo50gaH/wAl9NQbY7cWaPkAEOcQ0n8ys7P3Wu+j++qzEkD2T6J3Hx9vI+Dtv+YnILnNaIMaNYDJ/wCkN/0v/SaEYDjuDmuMwwDv5bfcz/NSLXSZBLtTDtZEbTq0N/z0qCHrfqj6V2M3fw1zmkHTWZGn8rduW11GquGGsw6SAD3hcb0HqJx7DT2d7mHuSPpbf5W1bb8sZLXSS17Pc0GQRxI938lPkLx02eWNTiemza+2Mxmhz2Pc781rNDKtU5wuAD2OpNnZ8f8AfVm1ZFrWCwVC2yC1u7gf1kU4brrh6dt7rGsBtteQG74l7K6Y3VV1fzfv/nv5CrCNg7Cv5aOkJESG/agP+kw6pbXvDK3+mAQ6fH+Tp+Y1ctkNd9qtAIgPdAjdOv8AKLXb/ptXYW1gMdbUTUMnay2CW+5nu9F23/BW/T9P+bt/wi5Tq2OaM61rK97LQ20t4a6PY5u799rk6BFAA6tXnoSI460Br6SQVbHMh07g4iJII09Rv0h/IciPcG7Q4meJBA3fynbf/O0Jm+RuLfTLiWuna6e3tG33/wAj/jPTRnOe6txa0e0gEETJJ+i53v3O/wCoRLneCwkuJDoaABW4cj+ufc33uSbQ59zWke7cIG7Qbp26zt+l7Pd/NpFkuhrfdJ2gu9zQfpbGAfQ/cd/XQ921jdw2/wCjIHtH5zocHFn+v+kQF7hXVZrnN2vY8Eyfc5sAgy3+sxyjY9hMvY4bpLq4aQZ/O/8AM7PepveW2Oh21jiSNujpI9vuf+85v9tQIk7Y3fnuHdzweNuntb/KRXUo7R7W1uAcNs2EjQ/SaPoqDbrw/klrBuDhGgPYFu3f7UavcWvEhzWneCRrDf34/O/lO3qdUEAgu5AOnI12/wBb6SV+FrSEbGl4ltTbABG90tdHPvfO7+uncADue4BkHdWQY1P7+nu9236KM5wLXPrGxwiW8Al38p/u/qMTBrqwXtsG7b7QBEkCd309vsahaH//0fPN7GNaA+N7SC0cRzu3fR3u/wAGi1ucIAPtI3uB9vk3/VyYQ3a8ncGh2xreQ8jc5v730v30QVkMDAA4uAd9EHUbtrP0ge7c2sKuaYSxa71NxB2lw+m33SSf3fpe9S9WBDgGx9EDUifh/r/hFFxe5rbANQYHg7+S0t/SJmku9gLWgE+ySd2vdzP3XfvOQpStxqfuaAbgWubuMQPpeP58e9dBX+mxmW1EnHc0EEyXgmWmpzv5K5u8GHgjQS467v5Otn0f+/qeF1vIwan01t9Sgy5jSYLXGBuBb+a785liJgSNNw2uWyiBIl8sh+L1eHlWVENIkDSDrK1q8quyraww92g8B8Fltvx7G05dQmuxo9VvEE/Rtb/Id+erVldJZux9XzBb4T3KgkPo6kSCOhWe7qTKnUuFPovEewOLwB7tzy72us/lrD65SX4r8ljtpqcIMkaE7HBdBV0/1ayL3vte6QfeamR4bK/e7+1YsXrQqw+mXUtYGtLw0NZ7Ygt/zf6yMa4o13WZ4/q53twn/wBBcGp0VyDvrAD9rhucJ718f56I2x7gHBzmhoMQYcQfdse2Q2xU68otrdrO0gnaTHG0O/ktR67XPbW+v2WO3Ne5h2y6S5pH7r3NUpj4OMQ2Hta9vqVOG3musGCHRLg385uz87chCXEMc3aLAIeT7jt+iXO/m0wduLRta4O5ZDgJgu3s1/R+n70nvAFde4ODwdANCCeS7Ta5u1CkMyLXDX3tJO4EjWI2tb7Xf9L9F/YRK/fDg73NBr3RESQ7X87836H/AHxJtjH7XN3GBxoQdIP0SPzv5CZtbdrdthAI1LNdB/W9vtTSfom0lEsaGgAGDofcD+H0WfRUrXtaRJDX8xJdp8v6yE25whglxB3HWNfzTIj87+cUzYxzDuIJMBpPAHulzXe76P8A4Im1qiwqyyzYAH7mtPtYC6TP0vePd9L6ChbW3Y1zQHOj2h87oj93d7vpe72p3327CC0vPaQQQPpNb/mpy+hwAnV2g1kSRP0XIi0dX//S4NjWFp2AtadA4aOkf98/fSsAAMe8GAXcuBnc79GfbuT1VhxHbY0kA6EHQB3/AH7f/ITWtDT7TLWGHbpJBj6Lt4939utVurCAoWepWJc58u2QQJ10gfS3/wDCfzaaXNiRoZPcjn83+yhuBc8ufsIA2ta4hpGkOb/3/wDcYi4uPk2l9dbJ2na5zdQ0/Q2z/N+7/txHhvYJG6J7QQQNHiSRoHTPtc4N/wCggZLHNDQXyHD2g6O26hviugxeiUzGc8ucBLWslkHj3ZDhvdu/qLVdT0ynA9Hp+EPtj7GEvveLHOa33txm2u9jK7Nmx3p+n/wimjjkJAEVbLDFIxMxXCPENDoePk43T2VPHqAt9V9Jnc0O926mPd7Gu/SsatGnJ9MB3q3MrGgdWxlwjwFjA13+er1ddGbRXl4bixxJcwnRzXD+cqs/ctrd7LFC2rG2WX3uGFZWJue4foj/ACvb7tznfuf9tp2blSfVDfqO7Ny/NiPont0P7rRsz8mwFtOS59cd6gHfIn2rIy8azNdZi7vdVV6zXOl214fXX7v3t1dj1r0ZVFljGVOlpMHSNT+9PuYqr8jG6e/OycmSLSyunbEjY7c5sOPu93u9qr4oSGQRlHh0JbGeQlhlKJ4tg06vqu39n351+TtdWDGNWAxzi0xO6x276P8AI96rt6bhPxxbj5DnPkNDSAYewEt9SA3+c/4xdbm1dOvqrptfX6jnNcwyZa06G5/p+5lTWn8789ZdnSqMfqDqqrW7tHWXMsGwH+cptmNjLK3bfT/7bsVs4o2RvpxV4dmlAx4SZQ3PDrfp/rPNDZYXAFzbPz2uB0J7+oNr2bfcx35ilbXbWxgtrsa2yC1zwRpr7mtc0e3d+exdh1DqzeoYGPVnUG/No2+hmVubuir3W1XVjb6lbtv/ABf+EQrMOvO6aRU4OsuYa9124tG54tmNG1Or9T9C6r/tRWoY4LiZa6E6D1f4STgo8N1IgGN/LK9ql/WeUHqPM+6fEkQ1w90NH+E9u32qQ9UgkwQXDcACJI/kkBWb+k5uFW+wll7A4ix9RO8EfRd6bvpsbH060Gt1djTEuJEFgABj7/8AX3qGcZR3DDKJiakCGM7hqAC0bS/kDX93876SibtsssLn7naHxgQ+Nf5Tfa5Esc0aN1I9rK2+Xu3Nn/yKC7fILmHaYcJPE/8Akk0LUzSx7G2cDdGh0P8AKif+qSDAyyeAR9EmTIHBjZ/X+iqtbYlpMjXTvE/SDddj9qON7eTLWmdf3fH/AKXuSqiugBxRvuH/0+GJdtLTO0ES0DUEfRdt/lKs5xdI9QARy3uJ+j+9/YejOJaIiQAHNGoIG4bzu/ltU8DHblXncGupx2Gy2dA/afYz+V6n/npQQFmgxQgZGh1S9O6NkdQuaXVux8dxL/WcOW/m+nP0nWfv/QXV/ZK6MSrYzaKQ5rHzFQLT7WN02M9n0/8ACPe9BsdeKvVuIDnMFrGiA1zdC0hzf3f+h/Noz+rZR6ezEfS0gPL9w+nsDnOe2ysh35u73sVwRjCMREnjMtZDt/V/us0IESMxEZMcRdT8fR6v67fpxBn9Kfk0Eeo14LATpLWn1a3bv8J+k/7dYsbDoqzcxlLHChztPUfo0uHH8j1f+D/wqunJy8bGGLSWsxbHEuLRJa4jdtD3fSrt2/uexVzFVe9rDZXXBM/RiQef3VJIZOKd6n5o0jGAYCzw47rXX1fyknt6J1jpeQ7LwiH49hb65IljgeLLadzbGWs/01f/AFCBlXZJl1lgst19Gp7W7QDya62bW+p6f+Gt9X9Gnp9LKcGvca2HXYCQNCdrrHD6TEc9N9b1XfpLhVXuaJJ2kHaX/wBT0/zEOCXsk5Nao+nf+7IfKm4jNUeGYkOHimOCPq/TH6UOFifq+2/CHVMF1dthbF7XOFZY5hDnTJ9L6X57nLJaH332PyIBcCytxbwGmGMbr7drnb7dv+EWjczEuxnUvY2xjwBYGgSQfzmu/rf9tqmcWmioV2F7drQ7nlrm7mnaVHKFkGwRvA16v6zLAiPEJRuRHqjL5Iyj8vDKPzej9JLQ91dbXAtIc3ZI7O/ffKJjVkXsGPU59r/a2pg9zp9x2D2/zTlo4vQMjIwPWourm1sspbqIE6Os+jv/ALKo14l1FpfkMfVkVn2tJLCIn3h0/wCYpIGJmfbriG/94LJZZGAjM8UToP8AV2rI6Pm4ebVjXPZTVlOHq2tgVsc/3Xvb+8xm/wCl++j5eRTU79Se/wCys9lRuAc53LfbtDNrP3K3e96qdR6llZGXierd6raw41tIaDuI+i/bt9Tdt/R7lWdQ51d/2x8Gva2lrXbXF9g3h+z91sfmJsMuQRM536Qdv3pS/STlwxBEdDImvTrGURGPDKP99vt6vlVUux6XDGpZJhoFTy0/zlt18bmVf1P+KQL2uy6HN9GzIreAWvc1tX0TO+i+5wyvzv6lqoYhZbkBtzvU2H1Ld35xB244fJ/kvuXQMv3DjcOY5Oiq5s5hIiIBMtZWPT5cLLHDGcRxDgjC4gD5pV+lOf8A3ryeR0q0uLvTeIPsL3NJEH851btlir/srJYHFrZB1iRuBnvJ2uXT31OIJJJIk6xP4e1UWuh2oAHdV/cOug8hsr7rj6W4FldjXHdUQ3bqzUET4PP0v9f+ETiNodoGODtoHAJC3L6qb2kEGRw5vY/9+WNl4llEtc08bmvaZED3O8fpI701suCUDYNh/9TgQ4Bj4aHRG0Et10/O49vp/uLf6VVTU0+nd9orNZOV7S2CR72n1tm5rf8AB7VxKSHLfznT9rH0L6Bf6jG4jhtsrc4mph02ieHOfs3O9P8Ad9iW67Tex2m7nuZ/SfnfSXn6Snn842/7pt8tftTrirTauDePzfpvo1TC7ppfdY5j9zW0VtB3bu1tj/d/1liLQ7fYG5jTVj7R67xDv0Q2l21tZ/m7NrG1/ub15okpBfHL5/k/q2wy/mv0fnfTc84rclxwxvr02hsAbxo70tsfS9iudFd1Omy2zDaMlzQwPpdtYxwl/puY8ubss/nfof8AXa15MkoT/Ndenzbf4a+NUL4dpfPf/M4X0y19L8mcqo1Q4ua1jmmWT/NudXuZt/lqrkOD34/2lr6i2hotnXcAxoY5kOdtpdU36P7689SUk6vH5f4XysMOu2/+A+o9IOWbnjpwcOC817YiPo3eofS/7eR+oN64c3H+1PY2CTVvbUSWSPVa8Vv3en+7uf8A1F5OkoB/PHb6+XRtZv5qH83/AIH87/h/9w+idc9GyisuiizeSRUHOMxNbPcT42bXf+ivesnPdlfbMMZ7f0jHuBcNsvhh9N+1rt7dy5FJHD/NS+bc7/8AdrB/OQ23G+3+A9JjOtGVd6TS4EMM6aHaPaZP7q2cJ+d3rMd9R/5JcEkq2b5zs2Md8I3fR7XWxq13Gv0eP85Urtm6Rz4d4+9cKkq/2Mn2vbsiBt+j/r5oWV6Ppv3xtjXd/DVcaknxY8mx/a//2ThCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAgAAAABAQD/4RaQRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAAAAAEAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAcAAAAcgEyAAIAAAAUAAAAjodpAAQAAAABAAAApAAAANAAAHUwAAAnEAAAAAMAAAABQWRvYmUgUGhvdG9zaG9wIENTMiBXaW5kb3dzADIwMTA6MDY6MTUgMDg6MzI6MTIAAAAAA6ABAAMAAAAB//8AAKACAAQAAAABAAAEAKADAAQAAAABAAACKAAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABVaAAAAAAAAAAMAAAABAAAAAwAAAAH/2P/gABBKRklGAAECAABIAEgAAP/tAAxBZG9iZV9DTQAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAVgCgAwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A4QOcHMkk7TBawTId9Iwwfnf6P6CgxjgRuDiRrPPJ2jcPo7kmViTuJDBrB7yP+o/ksRg5gAdHuOpJiG6e32f8JDv5aq2wMHua/kERy8EjT8zc0+123amdFbWFhbtM6sBOo8fzd/tUya/Te0kEA7QQZbJLi7a2P3G/QQwA5vphoaDBO0gk8aNb/Ib+Z9CtIJrVlW59p9MDe5+gZ7pnR8uP5y3+nfVLOvh+SfsTBwHgPe6Zd/N7m+n/AG0/1WpprcMqS+0EhrR7Qz+tq79J/wBQt/J6nlG4ivRseA1+Lk7hiBxS+xfjxGZoDdFi/VDolA3XPsyXREGGNA8Iq/lKnm9B6aWurxXGh4H6Mbi6oxwx4lzmf67/AFFptqsuM5F9jjyGsO1v/RhNbiV/S9zieXHn+1omSzQ/dbceRNayDw99F9dvo21lpJ9wMSf6rp/lf1EEsBAEjaJ1EuGo92v52yP3fYup6hgU5FNmO9obkNG7GeBztncx39Zv01y5fV6preA25p0D5GrTz+e1IUQDHYtXLilCZjIfy7sSx202Vsa6J3WCCfo8Ob+4kzXa5hBHO7sNDMSN3u+mjMII3u2kawXECAD+adnv9J37yFYwvPt0cwlwYfaD/J2at93/AE0mKlS/RznEtJJFjTug/wArd7nPU622sG5pDQI3OGjT/K4/zmKNW4DbsafbG2YDY83D2pg3ZFgYAHe1veN2ux39dvt/S/mId06JGtpcQdxafzgDDi3kOGn0fanaHiQB2B9xDXCe40+ghVl7vYYho0MCAJ9vH+v/AAimDXWC1zgJJkHVv9dmrtv/AIHvQI6JMpfYq33P2PhocNrtSDP8n81//VpzS6tweHbXiBGgJgbe37yau4NaQ/bYwiQ2JGv724fR/qojQ8Fvpnb5bZDm/wAj9zYlsobr1tDWy4kuB2lhE8eTtzmu2JO0eQ0ua9/JiWuUHubtLWl4ZxOga3/g63H6SW5lbCCT2kDTnjYQhqgv/9Dgd4kOa4SYLA8f2o/NZuZ9FOQ5zy/6LDMbef6+0u3O+inFgZ721gE6OdIGh/8AJfTUG2O3Fmj5ABDnENJ/MrOz91rvo/vqsxJA9k+idx8fbyPg7b/mJyC5zWiDGjWAyf8ApDf9L/0mhGA47g5rjMMA7+W33M/zUi10mQS7Uw7WRG06tDf89Kgh636o+ldjN38Nc5pB01mRp/K3bltdRqrhhrMOkgA94XG9B6icew09ne5h7kj6W3+VtW2/LGS10ktez3NBkEcSPd/JT5C8dNnljU4nps2vtjMZoc9j3O/NazQyrVOcLgA9jqTZ2fH/AH1ZtWRa1gsFQtsgtbu4H9ZFOG664enbe6xrAbbXkBu+JeyumN1VdX837/57+QqwjYOwr+WjpCREhv2oD/pMOqW17wyt/pgEOnx/k6fmNXLZDXfarQCID3QI3Tr/ACi12/6bV2FtYDHW1E1DJ2stglvuZ7vRdt/wVv0/T/m7f8IuU6tjmjOtayvey0NtLeGuj2Obu/fa5OgRQAOrV56EiOOtAa+kkFWxzIdO4OIiSCNPUb9IfyHIj3Bu0OJniQQN38p23/ztCZvkbi30y4lrp2unt7Rt9/8AI/4z00ZznurcWtHtIBBEySfoud79zv8AqES53gsJLiQ6GgAVuHI/rn3N97km0Ofc1pHu3CBu0G6dus7fpez3fzaRZLoa33SdoLvc0H6WxgH0P3Hf10PdtY3cNv8AoyB7R+c6HBxZ/r/pEBe4V1Wa5zdr2PBMn3ObAIMt/rMco2PYTL2OG6S6uGkGfzv/ADOz3qb3ltjodtY4kjbo6SPb7n/vOb/bUCJO2N357h3c8Hjbp7W/ykV1KO0e1tbgHDbNhI0P0mj6Kg268P5Jawbg4RoD2Bbt3+1Gr3FrxIc1p3gkaw39+Pzv5Tt6nVBAILuQDpyNdv8AW+klfha0hGxpeJbU2wARvdLXRz73zu/rp3AA7nuAZB3VkGNT+/p7vdt+ijOcC1z6xscIlvAJd/Kf7v6jEwa6sF7bBu2+0ARJAnd9Pb7GoWh//9HzzexjWgPje0gtHEc7t30d7v8ABotbnCAD7SN7gfb5N/1cmEN2vJ3Bodsa3kPI3Ob+99L99EFZDAwAOLgHfRB1G7az9IHu3NrCrmmEsWu9TcQdpcPpt90kn936XvUvVgQ4BsfRA1In4f6/4RRcXua2wDUGB4O/ktLf0iZpLvYC1oBPskndr3cz9137zkKUrcan7mgG4Frm7jED6Xj+fHvXQV/psZltRJx3NBBMl4Jlpqc7+SubvBh4I0EuOu7+TrZ9H/v6nhdbyMGp9NbfUoMuY0mC1xgbgW/mu/OZYiYEjTcNrlsogSJfLIfi9Xh5VlRDSJA0g6ytavKrsq2sMPdoPAfBZbb8extOXUJrsaPVbxBP0bW/yHfnq1ZXSWbsfV8wW+E9yoJD6OpEgjoVnu6kyp1LhT6LxHsDi8Ae7c8u9rrP5aw+uUl+K/JY7aanCDJGhOxwXQVdP9Wsi977XukH3mpkeGyv3u/tWLF60KsPpl1LWBrS8NDWe2ILf83+sjGuKNd1meP6ud7cJ/8AQXBqdFcg76wA/a4bnCe9fH+eiNse4Bwc5oaDEGHEH3bHtkNsVOvKLa3aztIJ2kxxtDv5LUeu1z21vr9ljtzXuYdsukuaR+69zVKY+DjENh7Wvb6lTht5rrBgh0S4N/Obs/O3IQlxDHN2iwCHk+47folzv5tMHbi0bWuDuWQ4CYLt7Nf0fp+9J7wBXXuDg8HQDQgnku02ubtQpDMi1w197STuBI1iNrW+13/S/Rf2ESv3w4O9zQa90REkO1/O/N+h/wB8SbYx+1zdxgcaEHSD9Ej87+QmbW3a3bYQCNSzXQf1vb7U0n6JtJRLGhoABg6H3A/h9Fn0VK17WkSQ1/MSXafL+shNucIYJcQdx1jX80yI/O/nFM2Mcw7iCTAaTwB7pc13u+j/AOCJtaosKsss2AB+5rT7WAukz9L3j3fS+goW1t2Nc0Bzo9ofO6I/d3e76Xu9qd99uwgtLz2kEED6TW/5qcvocAJ1doNZEkT9FyItHV//0uDY1hadgLWnQOGjpH/fP30rAADHvBgF3LgZ3O/Rn27k9VYcR22NJAOhB0Ad/wB+3/yE1rQ0+0y1hh26SQY+i7ePd/brVbqwgKFnqViXOfLtkECddIH0t/8Awn82mlzYkaGT3I5/N/sobgXPLn7CANrWuIaRpDm/9/8A3GIuLj5NpfXWydp2uc3UNP0Ns/zfu/7cR4b2CRuie0EEDR4kkaB0z7XODf8AoIGSxzQ0F8hw9oOjtuob4roMXolMxnPLnAS1rJZB492Q4b3bv6i1XU9MpwPR6fhD7Y+xhL73ixzmt97cZtrvYyuzZsd6fp/8Ipo45CQBFWywxSMTMVwjxDQ6Hj5ON09lTx6gLfVfSZ3NDvdupj3exrv0rGrRpyfTAd6tzKxoHVsZcI8BYwNd/nq9XXRm0V5eG4scSXMJ0c1w/nKrP3La3eyxQtqxtll97hhWVibnuH6I/wAr2+7c537n/badm5Un1Q36juzcvzYj6J7dD+60bM/JsBbTkufXHeoB3yJ9qyMvGszXWYu73VVes1zpdteH11+797dXY9a9GVRZYxlTpaTB0jU/vT7mKq/IxunvzsnJki0srp2xI2O3ObDj7vd7vaq+KEhkEZR4dCWxnkJYZSieLYNOr6rt/Z9+dfk7XVgxjVgMc4tMTusdu+j/ACPeq7em4T8cW4+Q5z5DQ0gGHsBLfUgN/nP+MXW5tXTr6q6bX1+o5zXMMmWtOhuf6fuZU1p/O/PWXZ0qjH6g6qq1u7R1lzLBsB/nKbZjYyyt230/+27FbOKNkb6cVeHZpQMeEmUNzw636f6zzQ2WFwBc2z89rgdCe/qDa9m33Md+YpW121sYLa7Gtsgtc8Eaa+5rXNHt3fnsXYdQ6s3qGBj1Z1BvzaNvoZlbm7oq91tV1Y2+pW7b/wAX/hEKzDrzumkVODrLmGvdduLRueLZjRtTq/U/Quq/7UVqGOC4mWuhOg9X+Ek4KPDdSIBjfyyvapf1nlB6jzPunxJENcPdDR/hPbt9qkPVIJMEFw3AAiSP5JAVm/pObhVvsJZewOIsfUTvBH0Xem76bGx9OtBrdXY0xLiRBYAAY+//AF96hnGUdwwyiYmpAhjO4agAtG0v5A1/d/O+kom7bLLC5+52h8YEPjX+U32uRLHNGjdSPaytvl7tzZ/8igu3yC5h2mHCTxP/AJJNC1M0sextnA3RodD/ACon/qkgwMsngEfRJkyBwY2f1/oqrW2JaTI107xP0g3XY/ajje3ky1pnX93x/wCl7kqoroAcUb7h/9PhiXbS0ztBEtA1BH0Xbf5SrOcXSPUAEct7ifo/vf2HoziWiIkABzRqCBuG87v5bVPAx25V53BrqcdhstnQP2n2M/lep/56UEBZoMUIGRodUvTujZHULml1bsfHcS/1nDlv5vpz9J1n7/0F1f2SujEq2M2ikOax8xUC0+1jdNjPZ9P/AAj3vQbHXir1biA5zBaxogNc3QtIc393/ofzaM/q2UensxH0tIDy/cPp7A5zntsrId+bu97FcEYwjERJ4zLWQ7f1f7rNCBEjMRGTHEXU/H0er+u36cQZ/Sn5NBHqNeCwE6S1p9Wt27/CfpP+3WLGw6Ks3MZSxwoc7T1H6NLhx/I9X/g/8KrpycvGxhi0lrMWxxLi0SWuI3bQ930q7dv7nsVcxVXvaw2V1wTP0YkHn91SSGTinep+aNIxgGAs8OO6119X8pJ7eidY6XkOy8Ih+PYW+uSJY4Hiy2nc2xlrP9NX/wBQgZV2SZdZYLLdfRqe1u0A8mutm1vqen/hrfV/Rp6fSynBr3Gth12AkDQna6xw+kxHPTfW9V36S4VV7miSdpB2l/8AU9P8xDgl7JOTWqPp3/uyHypuIzVHhmJDh4pjgj6v0x+lDhYn6vtvwh1TBdXbYWxe1zhWWOYQ50yfS+l+e5yyWh999j8iAXAsrcW8BphjG6+3a52+3b/hFo3MxLsZ1L2NsY8AWBoEkH85rv63/bapnFpoqFdhe3a0O55a5u5p2lRyhZBsEbwNer+sywIjxCUbkR6oy+SMo/Lwyj83o/SS0PdXW1wLSHN2SOzv33yiY1ZF7Bj1Ofa/2tqYPc6fcdg9v805aOL0DIyMD1qLq5tbLKW6iBOjrPo7/wCyqNeJdRaX5DH1ZFZ9rSSwiJ94dP8AmKSBiZn264hv/eCyWWRgIzPFE6D/AFdqyOj5uHm1Y1z2U1ZTh6trYFbHP9172/vMZv8Apfvo+XkU1O/Unv8AsrPZUbgHOdy327Qzaz9yt3veqnUepZWRl4nq3eq2sONbSGg7iPov27fU3bf0e5VnUOdXf9sfBr2tpa121xfYN4fs/dbH5ibDLkETOd+kHb96Uv0k5cMQRHQyJr06xlERjwyj/fb7er5VVLselwxqWSYaBU8tP85bdfG5lX9T/ikC9rsuhzfRsyK3gFr3NbV9EzvovucMr87+paqGIWW5Abc71Nh9S3d+cQduOHyf5L7l0DL9w43DmOToqubOYSIiATLWVj0+XCyxwxnEcQ4IwuIA+aVfpTn/AN68nkdKtLi703iD7C9zSRB/OdW7ZYq/7KyWBxa2QdYkbgZ7ydrl099TiCSSSJOsT+HtVFrodqAB3Vf3DroPIbK+64+luBZXY1x3VEN26s1BE+Dz9L/X/hE4jaHaBjg7aBwCQty+qm9pBBkcOb2P/fljZeJZRLXNPG5r2mRA9zvH6SO9NbLglA2DYf/U4EOAY+Gh0RtBLddPzuPb6f7i3+lVU1NPp3faKzWTle0tgke9p9bZua3/AAe1cSkhy3850/ax9C+gX+oxuI4bbK3OJqYdNonhzn7NzvT/AHfYluu03sdpu57mf0n530l5+kp5/ONv+6bfLX7U64q02rg3j836b6NUwu6aX3WOY/c1tFbQd27tbY/3f9ZYi0O32BuY01Y+0eu8Q79ENpdtbWf5uzaxtf7m9eaJKQXxy+f5P6tsMv5r9H5303POK3JccMb69NobAG8aO9LbH0vYrnRXdTpstsw2jJc0MD6XbWMcJf6bmPLm7LP536H/AF2teTJKE/zXXp823+GvjVC+HaXz3/zOF9MtfS/JnKqNUOLmtY5plk/zbnV7mbf5aq5Dg9+P9pa+otoaLZ13AMaGOZDnbaXVN+j++vPUlJOrx+X+F8rDDrtv/gPqPSDlm546cHDgvNe2Ij6N3qH0v+3kfqDeuHNx/tT2Ngk1b21Elkj1WvFb93p/u7n/ANReTpKAfzx2+vl0bWb+ah/N/wCB/O/4f/cPonXPRsorLoos3kkVBzjMTWz3E+Nm13/or3rJz3ZX2zDGe39Ix7gXDbL4YfTfta7e3cuRSRw/zUvm3O//AHawfzkNtxvt/gPSYzrRlXek0uBDDOmh2j2mT+6tnCfnd6zHfUf+SXBJKtm+c7NjHfCN30e11satdxr9Hj/OVK7Zukc+HePvXCpKv9jJ9r27Igbfo/6+aFlej6b98bY13fw1XGpJ8WPJsf2v/9n/4TkfaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iMy4xLjEtMTEyIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgogICAgICAgICA8eGFwTU06RG9jdW1lbnRJRD51dWlkOkVBMDBBMkEyNzk3OERGMTFBMjVFOUYwRTRDMUU1RTdEPC94YXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eGFwTU06SW5zdGFuY2VJRD51dWlkOkVCMDBBMkEyNzk3OERGMTFBMjVFOUYwRTRDMUU1RTdEPC94YXBNTTpJbnN0YW5jZUlEPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eGFwPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHhhcDpDcmVhdGVEYXRlPjIwMTAtMDYtMTVUMDg6MzE6MzktMDQ6MDA8L3hhcDpDcmVhdGVEYXRlPgogICAgICAgICA8eGFwOk1vZGlmeURhdGU+MjAxMC0wNi0xNVQwODozMjoxMi0wNDowMDwveGFwOk1vZGlmeURhdGU+CiAgICAgICAgIDx4YXA6TWV0YWRhdGFEYXRlPjIwMTAtMDYtMTVUMDg6MzI6MTItMDQ6MDA8L3hhcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4YXA6Q3JlYXRvclRvb2w+QWRvYmUgUGhvdG9zaG9wIENTMiBXaW5kb3dzPC94YXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL2pwZWc8L2RjOmZvcm1hdD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyI+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDxwaG90b3Nob3A6SGlzdG9yeS8+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4zMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6TmF0aXZlRGlnZXN0PjI1NiwyNTcsMjU4LDI1OSwyNjIsMjc0LDI3NywyODQsNTMwLDUzMSwyODIsMjgzLDI5NiwzMDEsMzE4LDMxOSw1MjksNTMyLDMwNiwyNzAsMjcxLDI3MiwzMDUsMzE1LDMzNDMyOzE1QjRFQUJBOEQ5RTYyMDlCRDJDMjU5REVDODdDOTdDPC90aWZmOk5hdGl2ZURpZ2VzdD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjEwMjQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NTUyPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4tMTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpOYXRpdmVEaWdlc3Q+MzY4NjQsNDA5NjAsNDA5NjEsMzcxMjEsMzcxMjIsNDA5NjIsNDA5NjMsMzc1MTAsNDA5NjQsMzY4NjcsMzY4NjgsMzM0MzQsMzM0MzcsMzQ4NTAsMzQ4NTIsMzQ4NTUsMzQ4NTYsMzczNzcsMzczNzgsMzczNzksMzczODAsMzczODEsMzczODIsMzczODMsMzczODQsMzczODUsMzczODYsMzczOTYsNDE0ODMsNDE0ODQsNDE0ODYsNDE0ODcsNDE0ODgsNDE0OTIsNDE0OTMsNDE0OTUsNDE3MjgsNDE3MjksNDE3MzAsNDE5ODUsNDE5ODYsNDE5ODcsNDE5ODgsNDE5ODksNDE5OTAsNDE5OTEsNDE5OTIsNDE5OTMsNDE5OTQsNDE5OTUsNDE5OTYsNDIwMTYsMCwyLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDIwLDIyLDIzLDI0LDI1LDI2LDI3LDI4LDMwOzgzQkQxRDlGMkU2OURFM0E4OTMwNUQ2QkM4Q0I1RkI5PC9leGlmOk5hdGl2ZURpZ2VzdD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz7/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAEgASADASIAAhEBAxEB/8QAHQAAAgMBAQEBAQAAAAAAAAAABQYDBAcIAgEACf/EAEQQAAIBAwMCBAUCBAMHAgQHAAECAwQFEQASIQYxEyJBUQcUMmFxI4EVQlKRCKGxFiQzYnLB0UPhCWOS8BclNESCsvH/xAAbAQACAwEBAQAAAAAAAAAAAAADBAIFBgEHAP/EADMRAAIBAwMCAwYGAwEBAQAAAAECAwAEEQUSITFBEyJRBjJhcZHwFIGhscHRFeHxI0Ki/9oADAMBAAIRAxEAPwDg+HpmsttZC1LJNUxywCc1m53jVCcHbxndnjbqxVGop6iCopoKWoqbbGEnjDFWi3knxAB3U5we2D316la/UlJT76uSveFg/MhWNSVyMDsOexxydCZquoWorrpSK1PVU9OMTRnDlmYLtyPqzk5Ht31kUPjPu61n0YlvWmC23GjtlzoLvVUdNV1FPkxbociLjIbB43A847arW671FbJPBcY/BnaZquGqpwVYOSSHXHCtnv7jQ2noa+ojjvFK1JRpLHioSWcIqENyFB5Pvge+vEtxpxTinhqVM0sjs52nOwDCgHt7k6j4R91Tk/tUZPEHJ6Uejlj+Tkp5ZEV6pzJVGIeH45wUDMMduc8fc6i6gNXXV9A8kbJOtDT022BQ+TGhBwO5yMc6AWdrnc7hRUyiNoGnEdTJgbggBZjkdsKMnRq43egujxV1JC1GZlIiYDayBDtVge/p9tcaN4jyc/xUlTaAxNDB83FSxxR18VPNO/mDKS8gAyFGP7c451cr4ZbWD48U0gkpRVpNIdokXIz25BByCNW2mqLtAZK4TCbYn65UBWwcqcLg5785OisqLcqdulrfWSSXBIPnIHckoxbiVSxPHHI+418rqx2Y5pk7fCA61VEFJLPUzTCUQzPHJMUXflU820KO+QRyPvr1eLbUXKjKtdaKletkyzwoeEQZjXaBlRn009dJfA7rrqi4RC326oWipQitJKNiSAx4BDDk/fGtMsv+ETq6cQrcbxaoZYpS/hxzu+4/82BxwO2ixW1wzDb0zS653YPSudZKezrPPQUtckqTlVAYGFVnCgp3JyuSc/nRTpfo7ren6kQTQh6JGjmbey+EmASYuMDJzwfUa7Dtv+Drpuaohkr68k95Y1CLETnJ8h5J+/GtNtXwT6LsTJE9hSppkHA8FDH+4Hc/cnVgmmPzuxg0QDHSuEpfhDe7jQRUcVOFYxGL9PJJwWJJZRgjDYAOp7f8I+trLSU/zdlQRw0/6cdO4y7g8BgcE8dyBzr+hVwtliSlWjorVSU3hrtQCABT+McftrP710/RSOTPSwygdtg4H3xyD/bUpdOQKFyTRI13cGuHaua90Uv8OvNmnoFBy1RDAqBTuB2lT9QwMnGP30PvlV1JUXmrS3RQS2KWd5IJqREUFm+kk4zyCQTjOuzrl0N0z1NSyW+6UMFUCCPMP1FH/KT2H2B1h/xF+Edf0jKL/YWeS0QndNSrArgKFIxsxkgd/fOkJrQjzIM/CiNGAOKxS4TQRUsVBR0BgRyqylB4rllPlVQOePXHJ1CkFI8gtqRVsKR08ks1S8I8NectvU/QR6c5OcaumSai/wB+tlJX1NPDE5kqJ6cLFEj+oCndxjndjHrqlPU1QhGRCtK7Cepqt5/WBH0uDjyj2XuTnSIDD3xXREAuT1r1dTBQ1Zg6dd46e3RhlbeP1NyZJZjnk583sOBpfkS50dR/EhcfkqhnH6RYtAQRgrnnPHIHrry1a1NV1C2pX2l18Mbd77T6H+oHtj20w1FdS2OwT3ZHghkl8ItbZ2R/MMhgFOcD1BHPvo670bjnP1pbf4b8CqfTsdJf7nTQ0dFmeUMZRIgjp3jA88uwc8Ac8/jVC7Vl0a40ksVVbkEM2ymKRtGu1e3lIxtI4x30Q+beugs9bbrxV0r19LNI0cjDiVZMBSWIG0L2ORnVWtpagUS1bGF54GWNBFUKr1Oc7izcrkHuFz6aJjEmfv8Aquv4m7noainpbTFWR9RU0ci0ZmaPwaUCXw5ynO0HCgEZ5PqMa/Xm3UsNChokWOMTyU7vVTGSZ12hlKqBtUkHkempZaWWO3+K9hkjjkkSRAZDtCHgEnA3DOfN2GrsYFvpoqlKaiigSpjdaSaXxNzAcsu8EMpx7nkeuvjMeKA4IbFAKH4a/JUjX16qcqNwjaRBDCzjsqs3mkJ7eVcffRmzUlxmslTb5a+ekiZyZKenK5ZyvducqPQeuo63qSkvTw3daaoeOleRqmGoqxK0uRnyYUBABxwMDtoWiR10b3KxVj0aVkLSSRMviFsfUgDd9uAdTkaWQf8Aoenw6VPc5O5qvK1ZK8tPTvNHPQSLTxU2AGLYyc5yDuHf1178Smr6I0tVviqY2LVBNRjIJ5EZbkH2GcHQyx3Cip6c21YTI9USJ5ZQTvkf6GjlH04IBwfY50UNDGK2jnoTCstDcfl6nxoi4diBnewOGjPOAAMZ1Bk2tjp8cfv8DU8Mp4715oIVorlF0/GS9MtQlVBUrCVkkDLghmHGMcHOi/8AtU9jgWzWehg3Ty/7xIsK7cAcD/mIHvwPbPOhJqbbW3x2tsk9qtNsdp9lRJumdycEZz6twvoBqN7lLJTm8tb6ekqUV4KdAcyTynglweTgeuoSIzsC3PH6/fpQXQg4q8LhV05qaqpZWMqNEd6nKk4wD6MBj0451BcLrb5JdxqZY5nKoQgXapxyoPA/76DpUXGdY1u5qw8SD9GWPACk8bf39dGXlWenmp0MKxpEs0SysMF88rzxk+nHpoTQhGwR9KnGpUFjU9PcpaWhY1VG00UjCGWGRYpZJoT9IKA9gRyw51Vo7fYPkjd7W1Xbwsxie3oQzEsO8bnnd64Ov136fjcRVazTgTxLURvH3jYn/huOwzjgg4+w1Wst8lt9S9JVU9Q5JKuxjWTlhgHjhl+3cHsRoirhCYz8SPviuBST6Ci1krrdS0LUYrIa+PJZPnKMIRz2b1zpipeorfMUpL1C7RTbkSaOUBVcrhSM9yOw9PT76Uq6hiSteoq1MTBVDYjDLJGeFliPqPQ+qnvrzDcqOlma30EKRoEBiEg8RvuRwTzzz76Vlh8Q7uSevy+/lXwfYc4pisclDNbauipK7fNXQFlZlVSnh5KpkHGSc4I0jXa9VtHWUYqIYBUIgKwGANIWY993oD9/XUc9UbPTw0coZ7hKyDw4MMY9pJXtwSc9tMt7hrJrZA9y6gpZ6enUzxyH9RaJ3GEpt5GWkByWRSQvGnYYdjbiMg/f0r6PKtuxxSxdZ4sQtdbdIFpkkaWKNySk78eYk+nHbudQPd4aW2Q3C321FlX9RN6rJ/ysCGB7HupGOc69wyS1IqYbTbmmjdXDVU4DvM6YJ2oTtBwScDJ++r0NQtW8pFvxOi7Y5ahPDIyMMQq9+ONNsBEBkZx8aYJ8uCKvzdSVo6caruFfRGveDbF8iiAwRkAYdUAVc45HONXenrRPeKZbrcKSXwYqYQIYkJkmYncAqdu559hydRUnT1ue2RmGzNUVNTLHIiozI0MRGHDemOOM8c66b+EPwkstVVxXGW9TAtAoFJNUAyRQ9wGQHC++fX7jQ4YkumIj4yfp8KH5TktWXdF/An4g9XUBaC0tRAyqrSTqVAiHIYhsAEH34Ot36E/w12axVNJV3y5/xiqpDuWMQIkKMTklz3c+3YDW+Wbp+x0duWC2yVFSSNpdvMPxuOpJLeKaMKlLvBO0og7fnPfVmlhFBhgMn1qUZ7dqHw0lvpJQnzDoFUKImBWNf/p4A+2jVP8AKoVEFVTThuR4NQEYn7A8H++dVVp4UG5ItzEljHgkH+2oZZLc4MUmxXbtHG3mXHr20XftOadS38QZNGfnaXZvZpXZe8cudw/fnI1EnUcKbxSmWDdxjYcD9vbQSmalhm8tCzwqNplaoby//wAsgf20Du/X9joHMLrAQcgM82M/2OTqJvAg5NNxac0nCjNNdRfSQUmpZKgZ/U+XwGx77TwdLF3FpqyWpK+endgSFYlSPyCcH9joAOtrBcW8GQo0RPLwhsr+CpDDGht4pmqJfEt9waogceR5CCR/0uMH9mGl3vlYdadi0iReCpFeausqKCUCWYzKG+rs3HqD6/jVkX2KrpmiYpIGG1Wdchx/QwP50nNUXGlqHgqkIO4b0I4I/qGvMlS9NKxAxEy5H/VnSRvEDZpt9HcrwM1m3xF+GFwSoWu6Wq9tsy2+3xuVMTZyRjs4J9D31kF06fv89OKP5GqZ596vHFGmwr3A5xtYe5xxrp/516itmp48SR1HldACD+QfzpQ6o6PutdBNTfMFoVcRsJXZmK8YBweTkkDPpqZRJhuUc1nL20aBsNxXPa0ZShNvpL5RxvGjB40XxpXl/pDR/Se4wDj7aKS2i3Wimli6hoVSljjgmrGZiU3sMxRIvo3q2T/bX65UFX0pcbjbLoRZ6CkmMcBhp1Eg3eoTuWI9c6qSF6+iqaatKmgSWKFEjpztwMtvJY5Zz/MTn+2k5Mo5zwKQcbjt7V6vjUl1paGW30L1CORGk9LUiSCBV4KeEOcFfU9tRtsiolkppzU+LIy0iywb6csvGSQctjsDgc9ydeKaooLN4kzQlDJzAqOu0BucjA2jj2BP30Oq5K0UkV5hpbf8lRPtjIf5maJmYkfUcgls58uooNx2joP1piMkDHai9JXVcs0wrXo6WrnjWPxKtGC+Tk4weAPbHPpqKppunKemhoKqnapkZDPAYJt0B3HBWMsdwB7nnAPbUkVDfb+JIK+njd5AsvmTYYXx9EmONrDlSRz+dTWfpqhUzxx2JopqeETRTtHJKsfPnZFbH9ucemuqdgIJx8qVkHPFe5OlacW+kvNqtVVUyR4hlpCMywqxIJYJxsPpxn30DlsFdbOnaeKagqYKthM1vpFQ+OzmXvkgYVR/N66OU4vVDUGlmmKU8u5gsROyQDszFcEkf0nnU7f7QXaqikpKKouEc03y1S8sgjc05XBba2PDX/lHoOdcjdmbHbr1qKkv0PApUo7/AHK2257PVRUEs880RTYoYI8WSd+AVJOfuPvojWSxOgq0kkWYRiOtpg5ZkQnylWxhsHnBGR+NC6npaitdVP8AwfqBgqS+HJCYHEIAzu8x7ZGOBoxLV9PWeAy3ClqVeXGxY15k442knOcep4x6alOUYjwxkn4UdxGThTXq02ppvn0pmjWSKFPEVgrFs9l3HA74OpquvSkqXt9dTQTUlrjE0k8irKGnK42Kw7HP9saXpb5DVXpYpI/9zNMfACrgxqOcnH1HjknVa61kgtyK9NlHqCwXbtWQ4y2SO+FwM6gkDbxu70oFIbBptqYLVEKCohSVWZQKVEYS08+/6nb1UrnAHIzpbuXST09ZlQS8LtJTvFMAWGfNFKO6tnlfzjRm1RtaoI7bOsKV4j3LTNJ5Y1PKq7H2ByQNT5eop6ymiCAvGxWbwvEaQH649/8AKD3Un11FZnhfCninIX2nB6VWS73SmkhkoaWNNihHScLHKwI8ylc+Yfcj76I1rx3WjhW31M8ENQ6skcKLK9PLnbh34/TI5Dc/toPUUVXSYpZKed6806yqp5kK44jJJ7gf66it9X1FeIZIOl7jSUFTDMQtLu2mYhfMp4wSfQevOuCEOcqB8/vP7V9NEBhR09aN2a2dQUDLA1Ga+F2ZyFKyCR93KMDyrkAkqPTnVz5Wnt1K1/prSoiORK4kDLGCTtDg4YKPb1PfjS3V9a1lBI1Y9WTUq6NEFXYISB58n1O7t6gcZ0YNLNUW2pu06KJ5vM8cdUMneMhtpHAYcjuNDmifO/sf1oRfwTwM1SoaSr6bjIaOilepZYts7RgBn+nyqS2fyRqO4U8tVOJbvKGgog0UK09aqlmI8zJGBgnP47aArSNZaZLpcZ5GqkjBghD7VXvtLH+UDP5PPbXyyWqou/zM9VMskrU+yjpkU7EyQd27soHOPf3zp9I85dW/P+q+TA909PvivlJb6qpunzVJVK9NRwvK8SjY1PGAByh/mYkZb1Or1BXqKmO5SRTy1E84SJvDKiFOR65/Yfk6tW+90kN2qYqel+dho6OodpHRY95UDAOMHbu9OTo70NT22/X5aq4WsUlMojkEMU74MrLkL5iWbjJ9vTU3LSYDDtipSbgQD1NPHwm6Drr7TZrrXXba0DxJEcIBGG+ncc9z7a6u6Osli6doIbZbrfT00SfVHHgNIw9XI8zn8nWV2C5xIqU8K09FT0yhYoYyMgAfzH/t206WOsldFlhlSnUnAlIyze4UDk/n/PVjaIIOBRkgwuDWtrdIqOEPOAkMYLYlYIoPsfYfbSP1L8RZi8sVtqaWJVP1oPG5/BxqCrvlvo40jlo6m5VUnCRuxyPuETt+Sc6Teo6+repEVyt8NKGOQscp8VR7cf6aPNNgVZWVmJSABmjlD1vcK+T5QV85QEeIVwpYjv24Ua81nW1RvNNQrCsYGAgOS7e7HHOlKgmyssNFR+FHKDvfdkt+dErLaTWzSHbkg5z+NZy6uyDha3Njo6KAZBUdcvUN3/WudwqHjJO2KIbVH/j86IW7oFJ4xM8Q3yEE5yc/nPfTHSWqlt4EkhZg2CAvmdv29Bpmt1whZFaKRYFxgqiAkfcs3bVUZmY5JrRRRRx8IBSp/wDhrH4avIQzMRgDChfxjUUnRtbSDZH4sQVtxAfg6dzXUiT+HEs9X/W0X8v5OMf21JG0VQhVYDljnznJA9tQLE96cVVbnFJEvSniqklS7578NkH8nVOoschzEkSsmMANj/LTjW0ar4jbiozgrnI7fbQI/LxMyOjnBxknH9tCMhziu+BH6UnVVHNaphURwYIPORxx9x216S4Wu/yJCKUMfGVSi5BVvz/MT6nR+7UtMIHZopiAOFTJDfvpJqbtJZbpDcKAyQTxHOJYchh6g8eun7G/eF+elZ3WdAS/jyvDDpQr49fDFb1bqi5W8/L1NLF4jyIBk+GMgYx+2dc6VNPGw8SenhWnB8WHAwjNnMg4PDkcgZHHA12obzQ3u2fxCKTKzxmN4/E8y5HKD751zB190lHZq+ouVHWfLGRpah2BDQgR4VCVxjPJH2Hvq8uts8Yljryu5tZLVzFIOQaVJ6+0Gho6yos0FRa2d465YUPiwS/yYII2qy+hHfX21W3pu2JHHXwwLRVtRJFCI5tzDP0y8nG4HHBx/npeper7bEaqtmpaNRVSGOu2RsVdOyhkP35B40RpDaWtcVvWvpZ0qWeeFHhaFRHnGAy5KsD30k+5Vxgj7++tLoG5JHBr7a7bTWaWqmpLzFdp3fwK611zmnmqwf8A02ByMrwVKkHPOBqtVWy+Wa6mGyXaVqKYPPErzkzQv2eF+fqGdp9GHI1avFjt1xp/nBSvCYo1RqiKcyI7+hcryDjjJGoFtlFDGpq6ipeKBt0c3zikI+OBsH1c+rAY0QSA8M31H2KiwIIFXaO3UdJLHXD+H081RiNo6moZUB/nLdy3PAAA++mI2ipFBUS20VKq58Umnn3eK+3AjBZsqPXgaBw0sN5pfkLzU+NLTt4qtJGFMsbd8jkHn+YZGvidGV1HdQY2paKgjVXFMHKvjOQcgebPuNBfGME4NQdAOCagrrxcY6b+DWmzhKWOPFcHfdJ4p5LqzDkDtgjnVOK2G7W6WolrII/lv94ieGLeykcNGiE+o54OM6ln6gvUFB8lS1cN2dp45WppCZTEC54DgBgMcHODqFmpq24U1fYrjHb6mjmO63LMJYhJ2Y+5yO3JI10ArjPAHfr9an5kGOlLF0okSumrLO8m6ljhiETcvyeQSMfvx66Km5WmC9WqG70FSaa37HMfcTtnLt7Y7D3wNMlP0XdLhHNU0NPBVtUN4maJkMi7D2ZScnk84GkJLDWJVR2q6QSPKsrmN1BGATlsn7HuODzo0ciTDDHoPz6UNfMOT0pkqpgbzIaymgqaI+JLTTEAtEzHP3zHo/03UdRVFNilloqWNQyvNHGixyD3OeQONL1FZKuMFKKpleJm2+E2P0iRngnupwcffValt1TU1W6xVr1McuWeJnK8DhgUyRuHoQANKsqyLtyOO+P39K6xTbwcGm3bbK2siqLzc7dS/wANkEu+nqfEqWG0lz4agggnsM9tAqinobZVVN56dM1WGnEKR4xJA7LnxGPqCD5cffJ41HUUF6eWtnp7dStLRRidT8oElmiUhXjfvyoIP39DquaBrxTx1dLUGjaWJYjTqWAcqcqQecfbnnRECxjk8dKK0hIAz0qRXp4R/vlwVokw0lO1CJN3vuLcgk8caLSXW501whuXSNnp7jRVFLmaolTIpBu2lcnAG3HHBPOht0pa2khhN5qY4ZpszwOzZlSNfKokIzxuzj115uCzz00TvP8AxBYnCwmGUiJJBg5PPm79iONcAUEHr+38fvQQdvvcivNQ92qJXeSSoioYXEiRsgZGwOcpjPAyM451Wr7r1LFcKQpUv8gzElGiAyEGTjcPMMYA/sNFYq++W7xUmiqKijVgFxGS0p9semfv20Nqbg71NRVpbXjjjQosM6Bmhwc4JPqSedTjJDcAEYqe/wALhQDipBW200tTPLYIWllhCyGOIQsodslS0fG7A5449dE7TNWR9R2ujshYPPVeMqK2ZSuNu3fgDgfb07aF0FdWC2TfMwSVHzRRpCvESxq/nTd/Lk4z6kDA01dCVPjX2SsrIQrlVhgC8bNz87f2A1MFmkGfvpQ0bfIDW69HWdoFghlU1UuMx7l35b1bB9ufM37a0i3ukIMalpWxhjApfn2Hv/fSZ03S1LQjwoiYSccnmUjvuP8ASPbWndNdP19SvjIfBhjGMhQpI9BnsB/nq/RcngVa5VeTUPy9xWEuha3ROwBEbL48h9QWH0/jQG8Wyc5CRMB5t28ZAH/fWm09kERM008skgBO+RMhR/SgHCj78k6pXey1dbHJVrTmGAjCeJxuA7hV9F+50lqEZVeDV/o8qBxmstp4Vp6WQIFPIXGcDOitqrKK2kvVKvh92Ib6mPZRofU0ssNVKspHhl8k5yAfTXunrIXmM8iR9vCiAGVjP9WNZLJPWvRFG8AjpTRFcd+7wmglllUMqK2MD0B98avJVW+QxuXmrJMgPEANob7+ml6F6ZXaUlBEp5k24LN66JUKXCvmAgkW30Td225dx9v6fydRo6pgZpyhp56hFaSGKOE8CJJeftzxqH5GGCUqIecnvISdC6KGOgIcUEtSQeJJHzn++rlXVyThXRXTBzgDjUSOKcQDNTfLRqxEe3J+oE5zqldLXSxMtUQQ2MYHIOdWqN95Mj4BwAxPB17uAD0TFWJwcEdwdDKgUaRBtyKWq2pDU3y+4YQeUn0GlHqECOkWOijWWqk7tITtA99PM9AHplqljAVvK3GcaBXKgWOnkWRDxwCB/bQtwDYrkiErkUjUJr+nq+OS7y0xpqk4bw1K4z649SPfQr4hW+2XApSylHg24EezyFGPr754OhXW9wq6i5IBM5jjYoqE5BI9j76q3WSsuVpiuNFKqvBGI2DnBYe2daawMkabW6GvM/aG3iut0sXvL1rnq90s/iXOgSipXUeRhImHqo0bG9WwCzg4++NLtPbLvTz0lyrZ1RaWpEqgEjEfq/HtjGn1Xo1aZLnXyU9wgrSaZGBbw3Yc855BH/ntoTT3qSeolsp8B5acCFauOAo0C796uytlSc5H3B++mEldMhRx3rEK7KCpr1ZhW061c1pmL0t0LYmjIllgLZILRgg7cZ/b+2pLdRXGjrxUR3q11kHhmCSTY4zkcrtP1k+3cHVime0dQzU70cMHztt3JW0kP6aPCzcTLgg8McMB2BB7aoW6mmW6T01pqpxCd/i0lUBJG4B5aM/1D07HGhFjyD1x3H3/AFQRI/Izx8qZL1K9umjoOmt8Vvp1WVKOJd4MrAEtlvNuHqAeNV7pdbjHZKKrpZammNyq3kikWbfDHUxYViyDzIpJ/H5GvMtHckpqOS2WwyLIkklSzTZCxA4RRjJLevf7aoVdnnqXAtlfHHtTdJFNCVDn13OpDLke49NAXlgX+/nXUG4gE5/f86OTWuuWlkhu8kNJUTJsqKa3umyomYbkkTAzn3Vjj1Gg8lBc56ZKS3WlLfTPHmWppYwJHxwWdzy2T3UYwdXbNVzV91SiudBRFRUrM1UKliAqqAr8fz44A9TjRGpltFzNZS01uuVA8Ux8Mbj+mv8AU6Nxk8k7T31FnZXJHX4dP3rtxDJD5h0odF0tU/JN8pXRH5WPxFLHDwZ7phfNgnkeoOvT2ZLtQzwCepqhNHzEZds7yggBueTjBwT7c6oJSyVLRSUtNMJKd96yOxZahVzuVkznJHtqxVUtMLZQNdVqo4ztRK2lzleSykkZLEDjB540MsWIIbnNLLll4PNQ/KXOqqI4aeOWGudysgkcqxQDadwHByBnPuNeqClpal0nNohjd3DvNUVDx+OI8oUbONrEHt/Nxo5dLrXW6hpaGkuLQ3GrkG2sWLmGI/RiN+ee7EaEx2ukWztQwzrXVLkzTyyxvIRKeDjPHOO3fXQ4C5JwT86MgEoLEc0RuEd1NJMaahelMHh00NSsrn5imZclWPPtjJOQQNDYKB6aho5KKkZZZV8R6iVRup1JwMA98gZ5zj017/2iu8FH+qnycYcLsjTbkBfb/wA6jvApqC9xPd6uoa21gVqZBktGu0ZyBhuM59OOc6FGHJ2j/v31oW3z5AonFDZrzbqqu6kkZRgRzxSTeHHUoDxsY4IZR5jjg9hpJtNkiprvJRU/VERRKldrU5Phtu+hFZuGYjHB++dEblaRe0nqo7XJsRcOPGILAHAZT2IIwdXrb03S2yWCnnEE5rRHUz0aoRs2A+GAcYBPBJ4++nIXREZS3J7feaKEYDDmhzXBuoal5aqG6GqpoxGZEmEIrFU8bmxwwH83cjvzqlUPH/DENHYaisLMUlemifxJWBz9bKSVGe4xk86N1F5r6hPEnqIa23wuPElVyiRk9w8YXcG+5GD6HVGTqCy1xehprhfbbNyqz0yGVTnsGVX3A+3f8aIhYkDbx8/3oPU4xUlbDWVFHRUL9PiFaaHbMKysmMMSscgDkZb3wANWukZBD1HSJCaeoLSBZTTsZ2VQeMsMKoHv6ffUMPS9JfqGNFkuVPcYd3iyVC7jVKefKGbAf12Z59PbSzb6BbfUTXkCeJqeZEVmVgF82N3HBHB47c6OgQkhj9/WiRquc/Gu3umJo6SKnePbLKQFCschB9h6t99bV0yzPEnzCqCBuTcCwU++B3OsL6Aqqev+Xrsq8RRWUdgQQP8AxrY7BepZ5RBKioCcBVwCB6DV3CwBpuU54FPUtNH4aNPUsp7tjl3PsAOF0OuppLlTmng87FSqqEyFx35P1fntqOvrYxTARNvcKRgKf751Sjkgt1IUExaaWM7t2cnAycnX12uVzT9g23BzWddQ2SISuFmBdOAqNlcnvnGliaVoV8BQoIbbkLjGjz9QVUtwWOIEROSZGYcgn014uVFFPKGiQK0mMsT6jWKnUI5r1XT9xhHFVYatE2iZ96xfQvux9ceujEfVtLTIzVEvh01ONrsBku3/ALaAz0b0s3jjcBCju3r5scf56U7tM5pRQRSNK3/Ede5LHk50FELtimpJxGpOKeLl8YrTSRinoUYSKfrkICsPwdfbd8ZLRMrJPRyht2ACu3J+2skj6UrLzWGeqplkJOAjSMoHtjGmyx9CtAvhywiBAMlWG4Z9wcaf8GBFw3Jqqa8uXfy8CtSpOpqav2mnhIEy7imDkfjRe2VJqjNTM3DLuXI741mau9tQwQggpyMMTyPbR7p7qIsyPKDv7Eaq5gAfLWgs53KYanqBIEiMDp3UupU8ZHfWddW3YQ1myKYkrwR9j76PVV4UTGZCRgEDBxrNeoK+OKocyNuZ3JHPcnQ449zUS5fanXrQOtt1XdNwLLGvndnGOx78emhc1sqKKlkhVy0EqkKQPpbHb8auXS7SmEUluqoo1UkSyMhkLH2VV5P3PbVKK+LUQtReMkssQ8xCkBvvg9vxq8TxkVXPSslNb27o658zVhF/oryvV4mpolqooHDyMZGOwngKw7KPxqP5Hp293KnimChZ1DKYHK+AIhk5yfMBg4z/AJav1D0VXW3CWO4xVEscgaak3mIx4Y+feeXXI7DjOvFDVmC2XWoqrfD8sakUMU8NNvkbchdwcemMZJ450aRnbzDggdq8unLLMe2KprarVT1dRV2WvqzUXCQLAslN4IhjIJcHBP1AHGCcjQ+Np/Bjq6OCWCiDkR/LS+G6qv1E55PPPpo9S2unrqe2U9qucAekLSxRuxSfeVI2hDwwHfynj20ASmvVLTTV9XVJcKCAqmwYCqwbAGR/wy2Tz68jXysHPJ5+P0oDnxODTo61dNZKasnqnjpSsbw3CHG5FY+ZJkPDrnnOR++paq41aUiNcbVRViSAFZqZo0MzAcDdkYBHPPI9joJYb9VTWK70iQ0iUi2pRAJn3YMUw3qxHIOGyD6DX3piU01iuxo6KIKamKWWCXLUzgkoVQnJznB4ORnOlmiZQSemfvPNDC+Gdwq/JNb7Yxq6u2zvDWSxmWOnAqZUIHlBYZVR98c6v09wp2kpntNHXNTV8hiElVnxEBGAzjOT5sAE8c6+pcxU0cULUdJHBMslO0cgwUxw0ZPG4Lx3IPOQTqjUR0NttottjVFQT7SCheSmOOTknhSed/c9joBcHgg5H0xRd/iJ5q/R3igR5XeCshr4GEUsTSiREqBk5QoOBkfbv66v0MjS22SsMtElLUqsj0sleElOWy+xVOfcaWPEFRU1EF5WVpFVqp3RAFqAOA64OM+h++v0IsiULPU2gPGGKwzABjnGVBH8w11oQDlR9P8AtCCBMYFfeqaOkr6+e+PUTOKthIm2oDqFHlVQMZUjHYHRSzz0c0NOsMRmjjkXdBKzoJiP6ZP6gP5WH99fKKso4USaoqFo0mTslCFVHB5Khc84x3wdWQLzMzVtNSG6UzRbYn5VJo/sMglhjIwMjXzszDB7dK62FIwK+X4UFfDcIhQNGYmZwgkYzIT78EccD0/bQqougut1ieWBZ5VpYYpzOMIJETb29jx6+mj1Hev4nCoudt2z8qJ59yMD2CuxUc/8x/canr2tNNSfwu40FapMe0TqwBZ8/wAmEG8HUFbYNpr4kYAxzS/RRXCeWtLTipmSPx2QhlBVGAyqj2Bzj2GdSdPq0dDdrt/tFNXOWiRMozfpmTLOqnkdsZ9hr1RUazV1ysVyMkJWJ1p2yWkkUjkBhg9uxxpk6Ir7TY+rrDSLQBbRHIlHVQOhEk8TqUdpHJySNwOBwPTUvF8LOOv8UeBS5A+NZVXxVFvuMbl4oapUUGpp6pXScHsjgjBdRwccH11BUS1lDUxw2pd0VWpk8KICMxsOGXKjnnt9jqKooelpLiLZQy3Sip4AD4daPFIftlNqggH14Opau3VAp/4fb7pBKqnar0pDTsxPKebBX/Q41eNjIz0+IoTHxGC/xV+vpbtSUSVlteOCjceHJvZpWWc4IzkkqwH0kcd8a92eKG63EUFtuJkqIwsjRSBXQgfWVUjBPrj9+dCVPgBrE1ezximRGkVMhyCTg+oGT3z3+2rtuqW/iCLSQV6VAhTwmyY9wPHiHGMjg/bQmX8/j/eaj0baecV0n8Neo55rHHUN4aNExRVXBG0Hy8a2SxXCC0Uy1k9QxeVt+AMsc98/nt+NcofDzqG4Lc2pKmZpY5lVYooR4gh2HvI44BPPHOtvtHUpetL1CbnQAEKeAcf9h/31YwSblB705GnidK2EdUTmF6l9xkfyxRufKo/b0HfQ+ovVRNQ1KvUOZTE0JY9y7f8Atj8aTG6qefIQo6bSxUD27AH01HHcMs6PUhd5/TTd2IXn88+ujTEuKs7ZNpAobeKmvo5kYTlZYgFcY+r3I1JS9TyTRgGU7xxz66uXyh+btCVgkVm3K0mP5VYY5/JGlD5ZYWJjIznt641mb2LY2K9J0ufx7cFeop/+fNRRzebLSIoJPr76H26xQ1VwjlZtviPgkHnj30PtdewSOIN9JIYe2j8d8jovAI8PjLZI5GkNpQ5FEkG44NMT9N09LE1TPGfCQ8MeP2++lHqD4jWa1N8rEZo5UG1UU7jk/Ydvxqr1Z8QZJKdbfS1khnqn8NSWwqA92/bTl8J/gRUdc0M19kutNZbDSKTUXCVQ1TU4+pl3cKo03Y2kt7JsHJr67ubfTYvFmOKyEda1VfWGF4KmOTJKb0KEj3GdGLP1YxqFp5lxIc4Ofqxpj6t6P+HRrp7X0T1VX3WsoiBPS1S7JSpbAkRj3GgTdAL4MtdSytHUQuQySnzbwccYOCDpq9sVtG2SVDT9SjvojPBnGcc0709te72X+K0jNvTOUz2GsympKyvvNRSSryrBQTk7M+uPXWu9CoaHxbdMwxMg2qfQ6odQWOltd3/iYTasnlY+n51UQypFJzVvOGnjr51d8SehPgp0fR9PdH2KCq6hnpfmKmvq6EzLMzHAiwOcf6ay+9B77TU/Vz2hLVV3hBUVFAiFTDg4OM/TnuNaNcqq9xU4NBV7kHKu4BKn899Kk9NU5mqayp+aqpxg4HC6vp9XWaAQ7elZqH2e8K4a7ZiSa5b64sFXbutKyr3bqWSVoZKmQkpCrjnO3sBx39e+rdBcK5bVRU7U4ZKNiauUSAiYuNvftgrjk6b/AI12OrtV8pbvS0k0kFyhEMyx8eHUIPLIp9DjjngjIOs+qaKTxI2o7hDRCZD4sSkNDUEDGdicDnuPTvjQd4miXmvPNdtZLO7ZTxnkVTpLJDb556qS41FIaS4qsUgc7IS/KuW/oHqccaKXeJ6avkqTUxiOpSP5lN6qJGPGfL9QJG4HHrr9051DQ3NU6Yu1wQuVMVDUTsPDLk48KbHJiPYMTlTj00HrY6iwV9Tb0iqSHglp6anmkH6NS7hRgjIIABIIONF2PI21jz+hqpiV3NNwrmtNOKm31sVRBUblDlDvj3x4VWI9QQRnQiw1dZY5klqXdae508uVEJO1seVymOPMPXnnOh9J1XLTSVSUNDAPAl8SCeVSXwMbgSOCAR2xwedHbRd1uFv/AImLnPQVVPuJMEaSGQn0fd27nzaVdHjyHGQak452rRKlr5q+2ijuYpI5yfHWU4HhkjD5Rff1yNEqjpilt9uiuIYWlZF2xOD40NSD6rGTux345Ghxu/8ABGpqiqdVqdoR6dYFLzFjkYbttZfXt+TqGvr7u1fUm5WastlW4zHJKJJYpEwWUKy5IGB6qcaXWJn5HSoopiJDVer1tDywTyTxyRKPrghXwg5+rykghSAMr3BGhs9koaRpahr7ItDNvqWDQCQnYM7VJ7E5wATr51Bc45K752xxP4NdFTVMlM0YZDE6+ZgQoIVSG8x5/wBNWOnqyknp6mKCplhDPgJMQybc8ZU4YrjkHXHR4hu7VBjt5Wh1nv1PWO1utyz0jyyAQtUuoEmeBkHAz+OPTUNTT9R3atlisdxkijpMxCMsV8Yg8sH7be5CjAAGi16tlmtlYtaimkqpI2SF3VYgwJ5dUG4tx6g5/GpK+/2CShqamyWupaWeBRMIanwVWQ8MVVk5BHmwCCM4Ouqynzwr19amhEh6c/GhVfXW2VaKKprHSfwxTNOSzGZs4O/0YH09eO+pae23GyikjuU8c9LVuTTRGNlWQD/5jDgn3U5BGvC1SmlYCuk3rAGSaNfMgj5CMmfK5GckEZA41FR/7RUqPWWrqJaySdFaakqiVjZG5STw3yPTHHtnOjLHlTk/X+PShkEHJ60SuFTU3epaW3vG06RbDTSRl5dq8kJLgZPv6/nXlKOtWCFbhVk0s0IaSFpVNVkncEjxxkgAZ1+slLcOpRNdaCoprTcYcuYkG2Kdh9XBOFbHOf341BVwzXuolqamnjguFrY/OLKAi7MAiU44Cj0YEjnQxHuOPSvozkkdqS1Sqrq56qnUQTQ/7u8rMQNoGFVSf5gOMavGa4LC6Q0UHiQqjhYUOydVOCCxyWH82Af7Y0dg8WooEpb9bkNxlRp2Eb7aepO3YHYr9RUfyqfudDUoGsk4lpHlMEEiOhL+KhGVB2n1UgkYH+WrJ3UnB7UQEYPPIoVclp6+UVMFNLDIQEqY2GUlj/qQ+pXH76juUtXW/pTqjRNt2VKOMSxYwqMByQOSMc+hzpirKNzRPSQwRPPS1jkr9DJCT/Ic4ZT6jQSoEFnjjmM6MlY0gipyp3rH9Ik28jk5IHpjOupKWPlqK449a9WUmgqrZUvVKot6y1khSTaz7SAMg9uPxreLJfYprStXBKdsoAklJ9ca5yuNSrQtGkK1EzJ4LOE+pc8DjueO3+mtA+HN7Siq1sdZNJM1UBLFTsQGRQM4x2JJ49dNRuFGTT1uW3gVq9L1VEa7wWnVfOAADz6AaOUPUC1E/imQFGOwZ9DyP9dA6HrbpqskFLcrJ4BBCqzRgqT+QODojHZaaQvPa9qo7byA2efTHtrgvkzhgRW4Hs+6puU5NO9qukF0t81qqnKiZCobt2OQP2PP76WZ0LExrIPERipbvqlQ3U06zRyu3jU5yuBz+P31SS8mprZWU4fduOQB30pfFJFyKsdGiltpCrjimaz+K6mN1MpUkZUYJ1NeIK/eJYaCUYXjPr9te7EUKiXDAnk4bAOmugjaaTZLK8hxwpPB/OqUybTyK0MkGTuWka0dPz3p97UEZmpnyBKSA3/+60a4dWx37oaq6Cuf8QsiSKscnyTjspzwCOx9dSUtpWmqxVRwEyKOY07aKvRW24MklTbiZBwzb9v9zo0N48LZjOKhLYxXY2zDIrObB0l09Y7vUXG1Vdxrq2dPD+ZqpQ5RT9QVRwB/prQ7N060dEZp4SA3mRfb76I26z24OGpokJz6KAo/86LPdaNlkp1Eh8JcM2PbXLu7e5O9zk0a2s4bVQkYwKQ6uSroLos0YyIxgYHbTj8vTdSWF4pAPHC4598aTbheIKm5fLQBm528D30y2Waps7R/MIRHIQckdhqsKseBVhtApJpqhrbVvbLkCCreU4xnX2qpqdS0kbjLHOSfXTd1/wBORXCmF3t4BkUhmUDv+NZ0LgVDw7iQhwQ3cHXWQkZFRhdVbY3Q1n/xmsUt86UuNCu4SrH48O1sHxE8wx+2dc89LwYnSolVHWjpJ66VAQSiY2Yz7ksPKffXUXUtSDEzSgAex5/bXP8AeZLF07VXS3hXhW4qqMgh8IgbtwxKT9GeeNWthIRGYyM1gPbqyV9k4HPI/alSXpu1UxjvjTVMqpL4ctOEBeI44znjH7aO25OnboUqJJS0aQrtBQjwNgOGIzhwfXGDxr9BfrDXViwVUqQOdy1M0rHEqIuQSOxf0HvwcapdOdQ1VfWmjhucFCkMv6UzoP0AfXZjknsc6dczOmWzx3Pp9K85MjFQrDGO9Epunf4dYbZcqZC1VFXkK8Y8WMleAox3DqwJ/wBNG4aOioY0vlpaKnilkdaim8sq0r48yEHkgHlSO41AiQxW5IKfc3gs8sU1K4KK7Agjwh9J/mOD6ftpVtdv6gprjNPK0gpapFU1UY8RGZDkGUHsSMg9joOfHUjcBjkVBWzkelNnzVzaaRbf1rFFNHiWGBCsLgN2A3DGPXkj7atU9Z1dBcfBud0roKUhI4p5pFkQO5wWOMjb9+3ONUZK2hqIP1ZKagR5C4qaKPMRXHlLoT7ZBxn8asSU/wDs10/Ui7KtTRyypGtPHXMEmgILM6gglPQgAc6XCgnHX8h/qhl1dhgVe6glp7XQUVkuVDItUkT0UgofNE0Xibo3Y5LZOW8uePbS5QUVnEFbU0tUitHMYIYk8RyP6mlDYIAHbHJ/bR+k6s6E6qipKiae5QzUqrTNLMM74V9XaPB3L2BIyQeedV6+8XbzyWe4R19FG7xwBKYLMpHIO8gkkD0OulGUtGBg/T+6PtXxMspArxYqWkgq/lJZZpkgXmQBEhhR84KkncSc/YZ17n6dtNoNbTmGup5pIAkbSlJA7sfKSwOTkff11RavtN6ojbLvSpNBNSuY5oX/AFElbnDcZJ4IOTgdwNCKuaooLcy0l0kmpTCoWGoJIGB5d/pz6MOeNdEeTjPJ7VwAcgUbk6eY0FypoLXSQtJHFVlgzIEljOHBUtkYU+nBB1TNirKWKrrKu4x1UVyKZK8mlKDPmIOV8vA9DohL1G1z6agIrGVYIEnkmZw7QcEZI7hW+nPI9xqnT1Zs9shu9suUAh2rJNM0YZwGOPC2fzBsEZ9e+j7pB5fyr7Y6jcaHSXqtSNb1bKKqE1DTrKojQmNVzhJSR3J9ccH31ahvtfPVC7xR0tvaWApU5lxGsh8xCA8GJucr9zqanvs/WNX/AAaKoang8wQKCgGMtvdvQjGMYx9tBKppK6Oejt1VUVzySBjG58IYYYK57bRjPcangZwRg/f5VNVG3kYNEaG9TXG6XC0Vcoo7gjuKGCGAtEdh/wCG+OMkchsdz351LDXR19QqtZdgJ3PAvEZkAwJEB+huTkdjoHIlVXGlqVWeNqpMGQuVD4O0nOB2wOM4OvQSnUvRWZTDWr5jJUq5yw/mDAbV5512QBj5eDQdwHGKtzmpUz0EkYBp1ILzKcKA30g+p9R76F11Ta1gSpnrIpoVkEbPID4kmeSEGM4Hbg+ui9ZOKhFpJ6qnrJaX9Y1EgIYk90UADy9ydxwPTGhtTJaKzfi31LrT4M0xzsg3NgFwoIUE4Gdw12ADPIz8q+jId8mp7ZSVVhqYq2ShqSHm3/L11MEQjI2sFbluD6akv16orX1JNebdToktLICmXGGO4EeGfRScgjGR7nXxEv8ATx1dsoIZampt8pecuxkWNT2wgyWHbt20tVMFVXePHNBM1XNIRh48F3JBOM9vc6ZRdzZejghCCDXRUNLQ3NKO8Um35Ws2ToeDgMOR98NkaMtdY+kqtJDIfCnwjRKmdx/q1mXwT6wkhpZ+g7jGnzFJM09IPqMjDzSx/jHIA9ta31TY6epvtE0IEdLMFeInkbCM6RumaNgh6fxXrei3Y1C3DjrQitrKGqusk1HVBkqE3L9iB21S+W8CQupYADI26N01gp6Ja6m8Fd5CTQTFeWCHkA+321SqZFcrIvKSeXO311HPYVaKPNk0Xtd28KnCI5k24PA7aaLTfJWkVhxjk86zuATU0u6mbIb6lPpovbap4pm3Hac575GlZYQeRTccmAA1bLaep4UAYplv5uONGoaqO5ttKAkf08Aaya33NVqA2QC64499Odp6gjp28MNg5yCOx0pgqeafjCsuR1p9tdO8cRTcEP8AUwxx7aHX2ampKKUU4VXYkk+pP/fVVbyhhJZsMfXPpofVMtUQHOQ5BBz3/GoljXwjyMmlGhvcVpq5p5vDR4iZJWb09dRJ/iS6MvUy2+nutI1VEShGdu78Z4P7al6o+Hct1ryomUUlYNlQpYgqPUjHfS5S/wCH7ouxJPLZ7aGmfIEk3nIH2z2/bTcMcbe+T+VKySup4p5uPxgolshhgiXxXPlA5BHt+NJNoDzCqqpTl6mQv/0/bQ2g6LaimxLN+lEx2xgYA0YI8ANEpCgH9tTeFEBCnrSXju7BiOlBL+zyKYdgPHc+msp+J1otVHan6kqrPLWywIKd1V2C+GfVwATjPtj862OdY69CwXzJkH86F3m0Cptc8KjcZInXtgcj1/fQ4GMDg/6oOpW66hAykdRXKclRL1PdI6ZKakg24IgjQQlEIxld5wW7HliTr1N07WwM1NEtRA8MQkZpYiPGO7ysp9Rj2Hp66lvdrqIknesRkSU7QqHDRyg44B7rjjvopSXJHtdEBJNNJBEwqJlbEiKnCKBnB4PYc60LSnYGjrxiUGJyvocGvtnrrpao5HentExtaK61UsUkM0aMc5SRGBYg4GCD3xo5V9Sx1cIaWAtcJJWkLwyFMjg+GyDgkA55HrofR2e4XWtgrZK2FU3+A71LKzzKy5xGDnt2Ax31FUfwS0RTVXyNQyo6r4k4MQLqw5UnzMe/fA+2lJQs2PX4UMoJH8vTtVy4x1dmr1rf4cYqaogTw6ZY3jl3jsdvYHPr6g6sxVkt/wCnzE1VI8sGZ2jeHcqQKfMhXOTtPbHbQP8A2y/i1ZK86lBPJNH4DOy+JGSCpTPAfjg986mp4GvFUlZTzCkq4cxVNLUxlGYNwpB9Cw9e2RqBiZADKMY71BhsbI6etRpQ20VM9QL0rU03lgj2qsrytyFwOAA3PfTt0c1TVUclsuVDGlxf9SELGyyVgX6lVs7RIAMg8bu2gdtWS2zRQXG0wTVYKxxzIvkIOeZO4IU4ye/J9NeaLqG3m4wW6soq2ikjdkdjUGQSqTglCeCobkD+kkai4aVeOajIxn6VLeBdorlB8rJ8hFUMzxBodvjAfUmzGBID6evODoKLibpMkFRHGVeTbDBk+c58wLepz7/jTldI0ttLIlDB/ELPNIPDdJDEyOeQh3ZCnOSD2I7HOrcVielsxuGyBzHIAktO0e8zMvIAHGAOTznJ9dA8VVUZHNBLEjJ4xSRdbZFTT1lJEIQciFXxzyc5K+y57Y1btBa0UgiuNPKbfR74pZ3iCtUxyEFEVe2dwO37DJ0MvlNXW6dRLbZqc7Mq8gkzv9vMozn7Z1Vrf471LUCO4SpRRQzeMsBQjcCoBbH/ACgYHtpqJCyASHg9+9M+J4o2E8UyW+7Uc95koxTU00kJKR1BUUzzqeUVwCB9vf0zoTcrZFfKhq2guBoK/bICZEKLG8WS0Y2jvt9O50GulooaN4hdFaepVhGwjiKMygZzw3GBjJ002xfn4IqguWp5aiNTIG3y08mQElyRhhgFS3318QsWHQn+Km+Q2VPNDbrWF7bT3Voy4BNtllp5jsilB3qQmPLuT0GBwfXU7Wfqy50Tz0NPvAGEWCnxGFP9Tn1IH0g51F038tbp7hbWkepaXcIolBYCePlPMRjLZZeeDqpcbnaa+U0dd/Gado/LuaZZVBZcldhC4Y9sjnGibdzjaOB3/wBUJoww3AVEbY1qjNTc6xzO0G40keHiiGDgSSff+kZI9To7eaoWuxU9JPb1imr4Fq7isRKR+Io/QiI53FVyzDjkjQuz2Sngljroeo4WBdoUhNO6iSQr5VIGQyj39xqnVrPFjfXwTVElQGrKcMXSUj/1MN2b0I0Rtrnr+4qO1TVJaWV5YbrI1WIKlWWSWnn8oJBK7gDyMDtr1Q3wSrGaitq3jgJZAzZJDY3DJzjOB+caJwU00VA7K1PlA0PgsDKrYJcbQCOfQ+oGgFS8ddBHVRxx0tLI/wCnEjZ2ntk45PqOecaMMSD5VM5x8BV+y9VSUd1eutNJUCpjqTWBlxuBU5O374yCB3GusulrpTdWdO096pYoq201SCqiI8slKx+qPHfAOdcX25Kuieaupd08UbNFLJCxDxBgRnjleOx7emtX+CXxltnTstV0/eKYUlslUMjqxMScYIbPIyec++dfXloJI8oMkVpvZ29FnchT7rcV0ndek42phNaeoaZacL4qoWPiKe2AT/ppcht8hieNKYu0ak4BzvI7gD39tTMIqikjqqKrhnglIZcvghfb76I9N3ahrL5UquEjWYRFR3RgP8j99UUYYZya9LQhiGBpdhp1afOxtr8ebv8Av9xqZaVkmSeLJU8ODpw6s6aenJuNJBkFS7ge3uB76D2l46glWC5J7H30QOGXNSOQdtfDSERiRQucZPHf8atUVXLGmJUK7eMDv9tGqO2NOoLqF2ZGAM8anksTnOOcjA9NLOwzT6FlXIqrTXZgQm47uwOeMe2jlDXIkySSSI2ByM/Tpems1TSnzjODjO3j++vxzTxvywYc5PbGg7cnimN7bOaeIrjFNKJBKpAI4P8AmNQVtwgiUxI5GTkEtxrPpepo6NDJVTiCJQd7vwg/f31Rpupb/wBQnw+k7BPdUT/9y2IoQf8Arbv+2dHit5CfKKVOZeKfUhhqKhnEYC7G3Mw4Os+6tvlut5lkmuEFPGufM7hQMffV9ujPjBcYx4twtlD43BSDdI6D23Hj/LQC5fAO21NV811ncqm4SQg4Qvxu78440cRKhzK1Ra2ZQSKr9I3yhuMi1FBcEqVlbIKHI/z01XaERMxCHa4DAkf3Ggq2GhpI6eKkhSBKXAi8MDgZ9dM/Umx7dCUlV3j8pZV24GPbS8pQuNnSgqvhgqK4y61tF2q+pbxHKyOKavbwlMygeHnOAB2x31X6ZjmitNVcBdoKatMoFLHuWMtg8kOw2jJwPvop1zFXVvWXUEdNFPHR0kxnqamMZKg7cjj6ufT09dClIqKKcwU1O2+WNYvHICqgy2e4zg4yO2daNGIiUEDHFeMaopF5IMcZNM1BBXm8eLcaCWP5dTIQ6AIDsJ3KewG7sy9jrzd7XBUrmR5XjgKSGqlUqyM30hyfKcnsex/y1H07WX609OVqzmkJwYqSmjwY2LNlmdeQw/HOqcVc0oapF0hoJ6hDHLTrK8kBGRz4Z5UZ9MnvpJ0w5Knp6UgwGTg9OlVJVprcq1Fwtq1eysMJDPsEU48zHHf6cH2PfRKnYNPVVtRPND8/CYn8UgnhwyoCOCPb11fW7Wy/VSW6/FKlnlheoSJG/WVPKAH4IYLnkfjnX2+9Kw2iaip45YEpK2qqGBki3KRGPJtY8N5SCfvrplB8pyCf2qODwvrVijhudyqC0VRF87aZRJDMAEJjZsGJx/McdvftoZ1ZQz2mvZ69pI6eOdpY/DLbkJ5yD2KkcjOD3HpqC2zMadrXcgI56uHa8oBLM4O6PH3wMf29dELVeLre4auz3+oPiUcCVFM4AZpk3YGz0YgZ786GFdDuUZA/b1FAAIPHSvvTt5udiuMUtnrDLBUSCoRZl8SknRvqRsjyj7Hsee+iPWPUV4o3pqh4WtlCsbgoJlCsZG8wB7ucdx37Y0Nnpat6OofIvFJGWSKKmo1EsRJ+rGRn769W9rbWQi3XvqS2VVuL+OIamJpGhcrgsGXsR7H11LEbneRkff60wqo3mPQVLUXahtVvhrKSpuNbTSLuXcwlghz2wGGRg9+fbVW2TUgtS1d1p3aqqGJ3+JkICx7kdiRyM5Bxr7N0zJ01QU9wtHVdFWwKAhSLxVaSPJIkI2+UY49R+dfrbDZ7u00aSQzT1LK+5p2hzGvLDbsw2449saiwTBxz8alEI3B71W6nsdFbLlEIaOomq0p4wE8TzvI4ywb+rIPpgAa9Ul3pbSsExtSUkuCPCgndgABhvFLcY+3fRS9dVRLcpHprNQi5SSBKp1WSd4iAB9Uh2jAA4UYHbUNe1dfYRWQ3WnrIKdgXgj2xGnlJwp24AIOPTXxYlQslBlbJAFKYvUr3IimglHhGOSMM5BZu6kng4zohPZrtfJXustDTtDCTuRJPKNxyQSOx3ccntqvQ19nqjUTtQolMZgoq67DNNPnIREAAC475z+ecauWu+3VYJFvMcNZTymWKOKR8qSOysi4AA7gjDDHtpt0ZPMgxj1qZRkHHAr7KlztdVFWVzUUrl1UUtGnIbuFGBxjuD+dVL71NTPVTUF3tkVX4ka7pBM3iRj1yynGM+h0yWY3Cjq5pL7aKSufc7JOCRK8Sx4ADqcBuQq8aoVlN07Szy1dst1PFUUka/NQVMXjTvNjIiQn9N/ucZ4PGhIql8uM/KuI4DYB4+FL0NDdquogfp2gmihhfxUTb4kY9CxcHAz99V66jhoYKljNCZYSVWnhfd5z65XKjHfk/jXy/tf8AqGnp6ma71ElPN+mtMkJiigfPMZQcA+o9xqa+W+3Wiip47cVhjhIjk8TzM7FAxbj3OcfjTmNpVSefT+zTMrB8etDoK2kUU1S03ydapMcs0LYLR7fKcD17gj10JnqI5zV0UiwqZCJY2jXCl1HbHbkZ/fUT1MVTKF+W4Y/+mSCT6j8nUkscZppIYopI3Y/zjBKr7n88Z0+q7Dk1JFKnJpq6I+IvV3TlCIaB3rKOEMZEnchEA7eY/SPT860n4O/Eqe9dQXO4VyeD4k0TKiPlU4x6+nHfXPiyVtREtvjLOiEkRL7+pI9Tx66YOh+ooekuoqWqbEkMgEdTk8Yb/wAd/wC+oz2kbhuOTV7YanNbOq7jtz0r+jloulJf7WqRVMJnVSArd9uPfWW3xZenL8YX/T3uGQ9wRqr0ZeKxFiltM8algGiHdDn2P3033aooutKFrXdKf5G8QKWTeMFvup9RrKmEwtjqK9FNz4hDLROxXiGqZGLHJIOfTTnC0TIHEYcnnIGsV6frKijna11uY6mFtpB9fuPtp0oeoa2kYJLnZ2y3GlZU2txVpHcB04607VlK1TSssSjewJHHGs26hqzE/g7CsrNtSMryzfkadrffoa2Jo451DYI79tAaS0FqmSZaCapnDnMrHG0fbQwdpyalu3DaKVU+GtFeKmK59Q+NcpYyGWCbinj9wsecH99ahZRDQ0YpoYvBgGNkUagKMew9NU6Oj8MYeiqEOOc6NUlNAG3eG4QccjRDdu67c4FG2iPha8yXq8TKsFHSxxqOC7cnHvpbvVrrpHLTzZXBJb3On+gFvLFCq/YnVPqRaL5d4oWUsynnd20M5bmpxqN3mrHKuiEMgMhJUttAJ4Go+qrssX+7so2eXaRzhe5P9hohUylLzFTtjww/fOs8+JtY9RTXc00qqyUssEbmQIFZ+CSx4Ax66LBGXcZ6VW6rMkCFlPOK55616oWeC6w2/MtVdLg81X4TkrT0yt5IwezFj5mPpgDSrHVSUVLBFFTKzVG6RPmFyB6cA/Ya9ObfZJZWtVY9XLEhQS7cK8mfMyqf5QO2e/f7ar1t3mqWhqqnaSF8rjIKkDHbsP7a2Kx4AVRxXjMkniyMxPU00WqvnrLZTWuz0mappyXcS/ojIGMtjy+p16qrzgGiq54Jp3ikhlkXnA9DvOMnIHfQCz3mrqZY44a+Cjk27QGULG5xjzEDGfuf76qXi2NSV+KieGNWUFkhfxNv2yTyPvnS/wCGUyYfj96VMALY6VegqI6Z4vGwJmfxGlWbKKR2CgDg+/J1pt5rXu/QvTtDV0iNPSfN1swnbzlZiFXaRyAAvtxnWTUFUq/LymMMkR8RVOOWU4GffnT707LPeqyKrpp3qquNDmmYgeIgBD7c+65GOcHGgXyEEN6VHazOF70LooHaOotu+djsJ2eIJMuHDA+hxj251JKtRcpY6ilipoJYcRVUZkCPMRzuYHGc59O+PfUVJUW2lrDWQV48KOdkgeoYLOyj6UPB5XOPvoz1NbgtymrY4YqqkqWAp5oCGIDRhgTt9c+hAI++hsSr0C4VkPHSpJ0q6V620xzukEsSpIHz5V4JaMe57bh++g79PU0l+huVvBho0VZQkI/4pUcRA9ucD78knV+qqK+qoaS51bywV1M4hkZ0GVRR9aE8EHPf9tVb+sFVUJRuklPRuoBhpSfEZ8cybT7+o7e2gxl0baDjOc9/+0JNycbsZq5SV0EE/iXa21lLLUSlWQOWiyT9SY5UjtxwdWIrHXU9bXSVdJHQ+LERHVxB5BIjHPlIB2ngasUgufTttoqWzwrWRVu5J1qlAXcozhVJzEwXktnB9NSWDq2kSOS31ktUlJIh+VKliI5RnLbuS0QGC3rjsNRfeMmEZqaM0bZTn51QvBtt5Vaqtr/lKiQnIl3+FIFGC2O4Jx/qc6o2w2qtbwrHLSQ1VM2IqGY5Woz2be3BP2P7ar3+79XU000MkFPG8ZUymOcYfPIO31HqGHcaisc9Vcljmu9ON0ayPvwBkDG1j9hoojaOLcx4+ef0qQUopJI5qaOptNNGtsuFu8SElVCAgqWJxuT1G0jGe/vorW1MlZWRWyz2tK2qqGSgSZe7yqezc4VgPqPsM51+tleKy418VzdJIaeB60/pbHp5UAbGO2CcdvXVG23evoDVVFHPAizRy+LMUO7ZKMl4zjg8kHAzqJGTnB+vBzXEyeCeKIGkpIZjSw1Rk3Vny6zmRgryHhnQHjuMDHpz7aD1dro7nUThK4K0hcRORvBeM+dSByCBzk9++iVsuMFO9At6mDQ2+4l4I4hhVR48ZJIzyMEZ9eNUrbYitWK+nuK0VfMZHjhmxtA5zIzDOzg8KeedTjXYSxPNfFAmGJqsaOr6copnqLvBVTkFqiiEe4U2PoYtkr4nchcnA5PtqhVy0tbV0v8AFZpqOlmaIyqp37VVTsz98f8A9tG7hDEXEVZmOmhjWJzI216lvQ+w+7dsY1Rr1j//AFj1AEBU+EY0wowu3aueW5OMnGjJNltx61NZBvBPWqFlr7a9yq2pKMRK0TvHDvWWJscLkHkN6hgc/tqr1BPb6Gmo40o4ah2jKtKJ3wGU4IAGBj++dXYun7hT2ham30glqJm8ICGZS0aoOcjvkkk6EU0vUVomjoqmlamaAOQ80X/DVsEkEg4PHGNPIoZ94PA+NNA7zu7V6qLrdI0SSRKRKdYx5Y6YRb1x7gAk/fS1JJ+oWj4Dc49s+miTg/NGasaOWI5IMjsDLn1yOc6oVCU6yb4GYx5+lvqH2+/503GoXJFHXPet0/w//EmpgaTp27ZliijDxTNyVTONpP2J411FLR2rqOhp5xVTRzIgaCYH6T9n9Pwdcn/Afpx/kp71UQjZWS+DFuHBRO5/v/prarDeLz09UG2JURoxQFoZOYnB5DKT2z7HjVZqdiwUTx/nWr0LU9zfhZDyOlMl6L0ZR+ooShB2x3GIZX7B/b/TRbp+60chWGoqYqhTwGDAjX2k60tU8Gyvp5LbJIoR0mi308npnJ7aqz9EdFXlzUQO1pqnGBLRynwnPvt7DVASf/ofStjHjsab4IenvF+YjnkglGMbMf5++mKk6ms6p4AmZyo+piAdZfT/AAqv6MqW3qcVKEZH6m1sfvolR/CjqipYn/aBoscHs+gMkTdWpwboxlRzWgDqKiSQFqldvqCRz9tX/wCOWashdTVJGxwR5tZRcfhR1rSAvT3ymqlz9LNsI0q3fp7rW1IfGnWMKfqE6/8AfXVton900J7mVTyK264XO0RReGlw8J8Z3Fs6zjq3rukp3FPQXMsqf8Rh31nHy3UlW58a5VEmTjbHzj9xr2On2UkzxszHu0jZOPfR47UDqaWe+ZOF60Un6werfFFIWYk+dhwvvrK/jT/HrnYIoLXAHonqc1c3ic+IPoUj2Oc6crhVmBRRWpcyZ25K+UDPJOlf4VSQdTXzqfpC9YqKerkkG1myMZOP7EZ1a6dCry4HUVntcuJ2ty2axajtvjhqePbBVtkmOoQBZOPoU+h79+/vr7cbJNUw/MSxiD9IMoBBR8DAxjnPocjI1+vdqmsnVlwtVfJJJV22paMDazeIFPlIA5HGDjRez0HUlxuRt9vsVdVR3BtxHhsD4Z7gHsOefzqzeOYNhOtefgODk9D3oPaEtyyNTVcCU5QbXBXdl/yRga9yXqnCvbxRLVxqd8YMXhYJ4wcfb9tad0x/h1+K/UNz8JLWFpZFl3TV8hjCEYxuIBO/2A043/8Aw4VfSVlpLjcevLYlZWv4EdHb6V5v+rc8uBkDQnQmQAjJPx7/AL1ERM7k9RWDWFBdK6ltnyUUBqZ/DCrnIJ/PbnGvVM9MWNPbpIaaup6lG3vJtZ3VsBkJPfPJB1r1k+FNJa+oKO8Vl8kmWJ0lQimAKuDjI82MepHPtqGu+Almq6ma7RdQ1SrMzPKEpI9qsTk4yTj8Y+2mPwcgbzcfn3p+HSbyYkquKznqimNJ1JULVUMsNO8ZrAhiwpY9yD327s9j66P2ytoI+naOs+bEZTfAodMCWJTwgPBJViSpPmGfXTfWfB+qWIQdH3ivvlRRIQtmrtkVRICpP6T9mb1CEDPYZOkKhrFobJU27qiYQU8MZ+Xhjjy4kZsuh4yhDDnP441W3VvJGqo36d/y9aVu7Wa3HnFD5p7jFCJzb6l2hq2fCDcGjfnaAB5ge/torU2hLo0s9ovE0UsCLMiKpRiz/wAhDchgeNFGt0FwaC3VBqaeWpp0zTiJjIFZeCmCcMMA7fbQqn6V6qtxNxgip1pkYMlWZSkowcZJLc59ePtpQSKw5O1hSSKjnLDB9apV3Ud8uVQ1ve1F0po0llhrUGxmGFwgIyM/n31egvi0K04eZo5FIBoYUXaqO3pk4bHYY/fVStrvn65oqyCsfchhW4U8JlUlvsccZH2OrdpttupZJK6O4UmZWCwzGOQPGzL5sL755xjg8jU32bAWXHy9f4/evvDUdRj5V9e4WO71ot9fUNaZIVMEcnyuWYBsqSD6Dt7AdtDqiaGz3F2kua1axMYlMDMdzsMcnHt2xxpit1zpYqINNOlXJTs+A9PlZc9ghkO4N39gfbQSkqKWqp6iokpVT5iYRK0gELqF54x9jjPcaGm0EjBwPv0zUCoUkmrSZpjVmQwpUVVmLYlJHiNIQuCexO0fk6H0Ty0NbT2qBs1RqFREXJCuRt7diMZyT+2rzX4FKGxVjKzGk8gibAMZcsqFm7kckE6tQ1luqLjX3a2tdjU2mmdGNQ8bxB2OxG3jB824kZHoNFCsM5HFcgjLsB61SarrJquV7QKKZqgMsdVUR5dTjsQfImACeBzxjVB6e4T3WmolY1MVRHD4TqDgpyWUAdgW7+p7aKTrDaKa311ZUCF3gENaQBtfa3OQPqO0rj1z2x319da2+W4RdEJ49GmUneEjxwM5w0f1Rr77c599TQn3k6ev+6kThiV6V6vXyqRtb6lqeadMNLbo23YLNnyvnyHj/hZJxobdFEqRMagvFWyNUwMDtBYEBUAP0lcYIPYapPZamjpQs0uFNU8zrtAkMi4Gwe2O59RkHGrFJUVFxpZY66CSJ5G8TwwvAOPrDHsCMA55OpbFRQVORUSO61IzLcYDQKGpbajs9fUIS7StnLFR6k4wMemNXL7vtFottsW4pb/FjarqnqpDJIFkH6UAQAk4UAkDjLc6lsFPSXW+IZvAloqOBG/QRhEjIckf8wHfn6j21DKlT1VdXeNI7nUNUTCGOFTJKruDtX7g9wTwrcaIjcgY/ujKpKbiKVJEpEqIJ6KNo1cskk09OvhycdliOcA/n+2hn8InuNfT0MQef5iVYKVomyDk9sEdxnkca1qm/wAOnVNPZv8AafqWkr6KmkkGGeM5UYycueA34yPvp9+Fnwdp1vdPfYrGtLbqZBNTzyMzSVUpHlkG7075OBq9tLOSXkGmSGiXeaYbH0vB01ZrXaoE2mjpxH25JAyzfkk6dbTZ7X1fQG31yCKphKmJiOQwGMk+o9xq4lgEs6+LDkg9wxXj1/z0IHzVjuz1CYKB8HA28H7fjV3+HAXaRxSyTtnepwaqulysNxbpq4GIVWQUpawfpVCE43RSEcj3BBxr9cunv4fH4woLlaS/m3U48emb8bSeP7a1Gey2P4kWI0N5p45pUAMUz4BifHBVu49OBrNbn0b1P0XdI6ek6lNGoOIoal3eFx6gNjj9wdZHWdEe2zcW/K969B0HXY7hRb3PDjofX/lC4711PZ18Wnr4KqFT/K+G/wDpPOrdP8WLnTxspSWKQ9wr4z+x0aS43etMcNx6fgrQm7dLSSxSbvfjhv8ALUdytnS1YFFX0pWq7ZOPAdG/9tZXxVPvLWt8w6NVJvizV1qkSUtS+fLkAc/56Gy9UUVSxb+DwCRhzJO+7A9TtyRqrJ0h0tLUK0fRd7YqD4ir4qp+SQcaKW/oy1SQ/OUvQ0KrH/6lVVnAP3yx18XiXkCoFWY+bmqcfUFHJup6ITV8+3iGnj3KPyeyj86H1NqvVask3UFclpoQBiKnYNK/2Zuw/bT1FaKtIFhjrqamRuSlHGNqH2yeM6H19iakhepgVWmHKzTSFmH39lH4GhtcdlqS2uTk1md/raagozTW2lFLTohMtTNks3sozySdA/8ADvbTUde36qVGCRxo2W4ILE8fnV3rWaOMyVtdUS1LR58JFO/dJjjHsPudM3+Fu3VE1ov3UEoDSVk7xg44IRcHH4zq/wBAVmmzVD7QgC1YMas19Cj9U3FoYFp22hpJkhUu/PIyBuP5196Et3hdT0dCgp28UHYc4cOScRnHuBnPfTXbqNa66zs0QI3hQxGCONNUHStHKYmagjeQtuRymG3D1yMHj863QhyMr1rzptRJjELjIHxrV+mLXBQ2aGhnp4HhXI8Rxlldzu2hgctjBwWycaxb/E/05ajY6BrdWKtziqDLtUnJhcfU2QCMkDafXR6uqesen7dDJQdUzUVup2eatkak+ZqFXbwVGcSAdsHlQc86xDqn4jXTqKqNBLdqgQvn/e58CeVcc5kX6gOwUdh2zqpXS5I7jfJ061OKYOBtpJsPWlXQtDXV9VHNTU5EclMeT3wSPf8AHfWyWXrLpqqt0IghpmMqBwkbbmVSfqA77lPbOdYT1V0xLJDU1FOrxqIkY+TnaD3wOMnVPoG+0vSl5+Qrp5TQ1Tl1JwNjn+VuDt9/zpyW1W4O41tLXXZdNVEUA5HetU6ivlKl/p3o5HFZKjj5hotoJDZQ5B+oHkH31m/xXpKqs6rPxHagpYFqYlSvjihLQtVrgGR1UcbsAk8efk986cOpEgcwXmyxb5KaUvGrSKVXA5BIGPzravh58Bo/ifbbZdKLqWmjjukRhkidCVD5y3kBxx7H24zpeWC3jgKSHHxpDXJjeP48gzkdBgfnXHNZ1TO9cOobRNKtMH/3uXbiokmA4Vm9FPpjGRwdFbbfKmoDVlfLFPlSAvheUOxyHPcjHbAxrtrrr/4cHTVBZq6r6S6yqFvE4SWSKpi/3Wd++Fxyg4Pv+Nct9Q/C09FVU1h6ptIjq6p1mmp0Y7IgpwrbhwwPcAazLWsd04ihOcd6zUenPOwUUoUEj1Udco8D5iIeL4S1G3xBnkgHhdv30Io7rSXG3C016Tzz1lTvi8JlAiKsQTnnkcH0Bwdap8PehOmupepJLZTdOKDQxPLPIpbf4e0+pPr21rXwzi6UtUlTFerPa7baIreDJFVwK1Okm7DFwctkjnA5z208+h/hY/Fkbv268UyNKIDlDnb1+vSuVbhYqyC2vT/M+NcFrMzMkW8lVHl2gc8k6B2i8XqjqhT1FEssVQ+JTUoVUHPIyRgY7Y10Tfulehb51JcKXpiCqWh+bU0jRnwJKdSPq3eo3dgw7YzzrKPihY770BcI4Ooqqe8WSvJanrZADvc99+Bw4xyuc4wdFfR51tzOq7l+WCPv8qqnj2MUFJdVX22pO1IadDChZZCuW/TXARW9T657DTHWiO3Wv+HJtaaoq0kZIyDvVVXYxPryxJz/AJaWaeCtusgt01CaR43Mjl1O4lhtAbjjHvxqzZbSlIt3bMkjUkMXlVSWD78ttA5HbuPTVZIqkYzyPzqKv4YOOuKt3aV6oyUtZbJXoZJkTfE+9g2DtIzgEj+nOoKK20dtjVGrKuGIBh49PGQY3A5bO4NnsMYI002Wz1fUlIlNT0M601TVeJLMVfehAx4ezvhl5zwNOdk+DNjpZWqOorzGYYpgq0yFkZ4858NgCSTg++fTTdrp11OoCLgfpU4IpJAQV49aQLVWVt8p6ShrQt4qHmSWnkpkYVbv9LNnHmJXAJOeR31px/w1VNWsSTdW9N2GaoUVYpKyvkqPEBPHjGJWUEdtu7jnOnm1UPR3TsC/wegipYUqPlo44o/CdcnueztGPXJ7nTuVSNZxTVIkrPKqLNtClseYBTycj8D176sv8PHbgmZjk+nSr7TNES/JVHyR6Ui2b/CJden0kknuPz8NxpkLVFndBC6fzRxkk+Qk5Pc4441v3wN/wwfCX4cype4aZ7hcpSmxquM+HDIUJCtn6sNyDwB7Z1klk616k6EqXt1FLUR2+pkZJKaSQGGN2H1cfQfsDg+utCtnxXvlsnEaTozh3hcz+dXLKNrAA4H476SkR4HzH0PfFaGL2XmkjaFCgI5594/Cq/8AieuS1NrrbLTO9N8qiVC0+0gPvBV2yTngZ4AI+3roT8KLhSdTdCWatjAY0lMLfUGMjMbxeUg+xxg/vpa+I1xv1/vUt8uLUzfNRNGssLksGB2lBGc/fGPfWa9AdcSfCTrqOhu9DUW7p28zeFNuJCwzMcJKR6MCdp+x57a0uiqY4fXJ5+FZHUtPmgc29yNpAyM966cms0LyZjk+s5jB4LnHHJ440r9R9NySyKVTc8WTnkH8e2n2Lw8mMhW3gbXR8hsjIbPt7Y1NV0ySxmEQYIGcMw8vH/321fGIMKzpcocVjtsq7lZapCCwG4ZHOGH/AJ1plvrLV1NQmnuNKJsgA7uGBxwQfQ6D3/pL9JnoUbD8goMYz3I++l6lqq+xOFRHQRkB93qcf66U2eEcdaOshYZzU9++GV1pag3Oz3ytamzvEDQ+JJD6EBgVOD+dLiVDxV8kMvVdQH27GXwHDZHZSXJ51rNg6rF0hiV2VAOSrcHkY2/cZ50RrOlOnupHzAJI5lzuaF2VyQO4I9QeOQdZ3UfZeC9Jltztb9K1Gl+1k9kBHcjcvr3rFamRpyEae9VpjP6h8Pep+2OFH7jVuWS4PT/7l0i5LLgLVVKDkdiQCeP21c6h/wBlekr49hTrmS6XF5Aj0cTb5E/5ZHA2rjPIY59hpWnvNquUVU1JPcnNMQCJa11C7iVOVGCcYyAdZBvZrUBJ4YUfPPFbyD2g0+dQwYg+mOaIUlTdCzTXa426hdQSIad/EkH2APA/fV2rt9DJSpcJKaUxlAI5a5y7O/ssfAz+2gfT90s9O/ylIkAkjxMGkw8rEjDe5J9Rpvmeuexi8VKxySzoYoKcQktCgzznsc+p1V3tlJp8nhSDmrOGdbsBozxXNXxSq6ipqJ6ZJGaYHwwoUCONDyVOO7e/tre/8OljSz/C23okSCaojaYkkeUuxJ/c6yzqXptr1UyCOlTwaZ1VAh8zO587Y9+f7a0Dpn4lRdI0dFZRaqarp4oBtEUpUqgbG3JGM4B5++tT7MDcxYDpWW9rQy24T1NHKejkouoZoI2yko8pY4zz6Ea0W2xxrTp4yBwDt3AEqX9h+dc/UHxZvM3xBp7P1bYLfa6e6SPNaHp5GLMgP0SKxyCR64wTnGNdE2nwmpo2Ur51JztyBnt++RrcwMHYgV5lPE0QDGr0cRSOPbFvIG7cByTyduPuMjn21jPUXw66Kpp7nYpLDsmhqVqIakNuJpp1LRRlO2FYMucce/prdY4IVWGSKRmIfeVAwWGQe/4J0jNarD1j8UqW3SyyyxUVp8OpWnlYAS+OdkcjKcHKHOO447ajqOxbdmJximNIl8K6VmXco6isPufRt18A2iOlC0jL5/CbJKgZHmHGT9+dArl8IYYafxIizVEke9IwA4kXHcsOcDvx9+2urr78Fac0AHTtwlGwPtgl3FVO71Y8qfQDOOe+NYn1pQ19jrHls96hKURAkppQd8beof2GfUf56DpV7a3EXByw654NW2oOJ7jxIxsXt3H+qz3om30EdJUdH9V0qJDUqZKetgj868YO7GMgHGG9jznRKwUXW3Q3UR6bqupJaMUksNZSTRVR2zI/AYY4GOM47HRfp6kufVF3pVe3RrKwAkjTkKxPOOPLxk4Oi3XfT1ys0VBLUxCemt0hEM0hB2ROcMpwM7Mcj2I1V6vJ+HnXw+jdc0xp0iSsFm5A6jJ5rrzpD4nL1B05Z5q6WTxYJkpK3xZA+T9MjZ5+3t30J+OPwctPxG6Qrw6rHdI1drVVnjBXlQ2OWRhxj078a5hFyuVFNBc+l7jipmXeWDM6SbcBWfnzZ7DIB41ck/xH/F6isVNQtcIIWinO92gVyu18FQCDwfbWeNlJHckRsA3X/laPUNBmgi/HWq5iPpyR2pM+FVrPT/VEVRNIYpDHVU80ygko5XBBGRx39To38Huh0vN4qW6mrqepSljnmFLWZ8JlydmT9O1uzDOeNB5evYP9qT1JX2uI/Nt49QYmMSZJKttQHyknnafKcaefh/VUkdmivc07uanxJoT8winaH8qcgYBB3ZPOe3rrfLAL+0FuThx3+PwrFGeaByxBwevx+dfbn8PrcLi9yoIoKaIxbJIIGMcWCOTxnCg9s+2dZr8fep7JcfhonSNxo6GlnrKqFqGQTh5ZJY35lb1VSuVz/nrofqO2U9pp7Zf6xmq6G6uJloYCi1IQfWg/lZSTx986zv4vfB3pz4qdVxdS/KS0NsiEUSUkZG+cqOPEK/SQOCB3GsvDfXdpC0Rfynj1re3lhaa+kT6XbEyd+cAf3XKnT3Q/WXxEuVZQ9L2qpr5AzGStQLDEABlRK7MEQY58zemtR6Z+DtjsMrXHqO4rf+pfAVQlBn5K3SL9MskvBnk4xhRszjJbWtUSvcrdTfDjom0yvb6WNY4KOhgVliVeVDOf+JIWyTIxyfsABqtVdIXel+atdfYllqoIIsxRYy7M36oLDnI+rBHGNNW+jQW5UXDjPpXnNtFJNkwRlz8OaE9M2CourUyDxFkmEj+HswzDBJIOO4I9eDnnTE/QawmGWSlqHkkE5WamZWZWJBw4x5j6cYxjjV6wzUMFRHTU1JTo5iS3yloD4jJITly24FdpAwMncORk8abaGwtXq9aKI1VRUCGkMlRl2kCvt2YOCHGQeB2763trZwiPC8mq+4nmLbZMg+npWYr0vdZJ62skpJqihoo2cuJApLsRhgpHlx9/X78ajoVraaopphEtZNHTtPJIzrjy/UT65AwOO2cH21tXSlivd5nvy3ChpGopKWVPnRS7gh3kEMOyhccZ3f8ALjWZUFXNGbi1zjjCQmSiAKBmkQYGwngbSP5R2zyTqjvDA8xtwM4q70MOr+IrYPbFBYeqDJK9NXWhGjuNRgpHEqsnHoc+Y+3HtzoVS10FNWqjTxtTpIZITHGzc4wAwzkFe35znRyd7fdZGiq40LIjREhiGiClSu1+cYAx29NAL/0r/B5kulDNI7THKRqrKxiLZyGGM475x276rRZocgdK1N5fX20EnOOfiK+3C5+Nc6edlIFMyysoycAuMDI7A/bVj4k222da9Mz09RAWnaplUAICAqjKyZHODnhvUjGqFpqaiurpqN6BjTSq0iypxEgDYG4jkMCCckcnV56xT06KYxGSoSZonmkkPjNL3CjIztxjOrOzRbSJgOFNZi9ubjWLhS3vj75qj8C/jKlgrx8Muvqx0NOVp7ZcZzhMH6YJCeB/yt2HY66SSVF3xtSkNEBlt/lIx++uOus+jIrjRC7GlWORmaNnGcOSAO/fII04fB/49f7IiLo34i15a3pGIaa5HLPTEcCOX1aP2fkr9xqUcwzSt9pxBznzDrXUSQibcWA/UUeQJk4x6ftzpdvPT1DVASMCVYlcDOQPQj3GfX00Zo6ihq6OKtpqgTQ4DQ1BkzE6sM4Vxwe+dLfUfxW+G3SYkTqDq6h8WQAx0tPKKiZjg4AVCSO3ckD30Z5UUZc8VUx20srhI1JJ7VTj6fkpJWkpjKrqAzZGcEHAb2/fONZ78WPiT1lNZ6qxfDWseCKM/wD5ldFJMoXOHSHuvBJy3t21JdviP1X8SKh7P07bamx2fZ+srgR1c0Lj6i38iH2U4PvpkgtvSvRi0sctzV0q4gVTH0kjB3j8dz/31m73UyT4dqM1fRaY9oc3i4Poa50pbLc6dUCWep8NmZZp3YbkK4Kuw/OSDnJB1APiBbVuREsRjdioeWRWCuikkMAO6juGOTraBRWe80U1vkgWeGXbsWGTwmEUbHw5GfAy3JXk57ZGs1636RvdRHT3iy9H0fz9LSmgjuEtTgtByoeSAAKXGcA7sH21YXGWVfD7jmnoYHSLxMc0XtRpqpXu6zxzU3i5LJJ5kBXcAnrlsf561SjvldcenEqKapCwyU2UhJ4ZCOMY9RzrMrd0GaS2222zo8rimSnkaLnfJgAFhjLEZYDbnGO2mLpxqJbXSW+RpEaTdGoLE4xIVBz6AjzH21n/AGj0s3Fr4y+8v7Vb6DrixXPgP0bv8ap2+y3KR7jU+F4dst2JamvmfwoMkZAZj9uNo5zrPL117dVt9TD8O7dTmWeJo5bjXU27acnDxRsMKfZmBPqANOPxS6gPUsDdBdHVxbp2018dPH4b5NXPj9Wpb+ok5Az2A1Stdk6coLa9PXXKKFZ428M7wHZ+2Bnjj21X6fLJaw+Egwe+KNrEz3Mu6TkdvgKw/pzpDqui6ltPU1bLJX1y1YeR6mclZCckjeeVOM8njXZ1p68pbLZVkrbHcpSUAUGWJA2cHG7cc/nHOsSulqp7bbqdaCro5J3GRshJbKY8oJ45BOT76delbLR1sCV1TKtczqT8kVYKpA4IVuckDn0GtJFciCPxGH0qotNPTWJRaLgH1JxRK+fEvrrqGqSjooksdklISRKWRpKmXPAzMQNq8g+QDI4ydXrLZbp0k1RX9O1U9DVIAKh4mDGZx3bw+zc/29zoat1WvkFvnkhkjkMT+EYuEYDylfb7nAxxprqpaKSywVctSHKxsPKx80oPAbt3/wC2qu9vJp8KBjNehaH7NadaeI0hDBf3/qjVJ/iQq7XFLbL90609U6qryUsgUbtvLYbPmwc8cZ1hnVHUdRNUmvSkhhUVJMzbdhwwwQmT9JHOP6gcaZuoIoKqemuSW4hJkETujE7nU9+P7ebGfvqvXWdb3HUGgp4hNvEJYIpWELggAehB5yOM51ZadaQxIJMYasVqtqHupFtvdPSmCzUNxtNZRVVjuRhuRRn3qc/MysgcKARhuOADyedVOquq+rhYpLh1PTR3CkkIp52iXY1O57bxjzDJH20Q6LlnrrFQJUxfNT2+odcwx7RMwJCruBG49z6YA9dE7nPZpM2a+bXpKuGRamBo1dUR04IIGc7uSvAAGe/OtcdPtdStgZFGfWseXlspSnpWY9GdcU4sluEFTJ85FUGlngVcq2XIwSPMOSPsBr71JQ3K7XKeMW2enofGV5VjAzTtkAsx57f/AGdA7RG/StfVQSVlDIImagkkRyzqg80MgPBIKnaW9xjTWep6q80rW1FkppU/UKqQMxxgDcDjzE+gPAz76o7TSLOebdJyynFaub2k1SxsRaxMPDkGenPWqXXvTLT9OUdLBKsV4rGSAbcrnOc7+PbGGzgaLdI9JXu7q9oshWjtFuovAkeVAXkdBgiNByzEnkj9tU7v1F81XxU9uqZqipAEEGF8VRK54ycDJxkcDuNPnTtVNYEo7FNNSIkUTO9OqM8hk3ZaNg4Ch3yGU+mCD76tzFD+IVBgAflWd/EukBPV29e1NBp6OhRLdKbhNHQU8dNSLU0haWFimNvLDgOSQ4HIOCAdfKWludlqd9NKamiZQ0iBirxStwMDk4Yg+npqtHeqeos6OJrRT1la7RVkbzGPEp4kZcHBJUAnJznggjX6kv8AQJZTNDWNLSU6frqsxcMQ2AJj/RjBDKcjtyOdOzWtpcRGFlGPhSlnqV7psouLZyGH60T+Elwg6aF1FHb6TxXhdaYyTOYm3RZl3ntwMlSD7DQajrlmq6gVkskgj80IkY/qLjIOByAAPftwNGOmKda2uuPTtknWOaVWVd0JLIrA+cZb6QSQSM44GNVrx0ZfLFeqSlklXd8mAzCDcZkBJCxHJLt3IB7D141i9YsnudQZLdhnsDWx9i9dstHjZrwEbscgZ9KRuo70YaqCWgoIW8CRgHcZPHmBYDOAcnH8w9Tpvoa5LtRRSLWCWhmgjwnC4lYjKq+7ykY7dyPbS7drjZ/FNmmmWlqPFES+OVAG7gIWB2kZOTuIH9tCOieuIOn6Gu6VrEFTJJO8NKUjVwSG3NsOMFuOGA7jgc6e9n7iexLW04I+yaL7cJY6jsv7KQHPboe1dV9AUcVFZpPG2y0lcxd1jQjcwG12LccYPb1x++sf+MfRa2bqqvr7VAsdOlPHHI7oS0isDgj03Dt7Y7kHW/8ASFO1V09T0VypRSVS05mI3LgPtHLHHrx6d9U7+LHUWyOquNEtTLWU0lE/jsxKwk+YBAMeb1+wyNZeS7ZbxpuuSazEQaOIbDg1x/bzTbytBRPWywUzzTxqxXZtUkyAHvjuT6/bVKXqyhNrhpkl3Vi07bpnJkQrjzKAOwXgZHvrz1pY26avdVb6IQCGoWdFLAEbccEngEADaFA/OleGjqLh8pBRwrmmk8M7UVnAaPnA9+O/p7a1EJ8ZA/r2pqXU5ZE8Me93NO9j6c6ibfTw2d5qOsMcsKwbAshYch3zlcj+XGCdaZ0/8B5pqOsr6tYUrKh8rECWCKo4yCOSvAIHGlT4D9e0XS1zjPXccX8Mq/ENLUxrvNO5AC5A/kIHJPr2101Fd6Wpt1FX2OppaiKVTHvgOY0GcsMjnAH/AL6ptU1G5j/8gfL61yCOS3O7oTzXJ3xC+GF5s9DWivll3pLBNE6zHZIN2CpwMN6dsY1lvV/SaVLxNWW+EO5LuwkAxIDymD9jkY1/Qy6WW21+2nuqQPTVMJiMTx4w27IIPOc9xpC6l+AXQldRKtLEsdXG5bxC23JdSNo/+XyGPrxoNjrexttz09RX14WulBPvCuOfh90fdLaVY3K4VdutgNVFbJZ3MZQS4d1jztwD/Kfzp4r+kOmjdf4lSdPKldOWqZYIYgHI34ztx5e+fx350yxdISdJStaJ6LwKqAfLSlJDGGjzkFsZXbnlcerd869i1CWnprtReEJanxI2aKY7o5QdwQl8FuRwPU5Gt1DDBeWpxyrVUwXk9nOJozhlqglNZ7vBC38PSFqQPTkxrh3K8hhg9ucAfbSP1bapbRLLXS1ryzsqxkSMzYYHCjnGc8EdwNON0vVFZK2lulP8s9NdEzVRxRmMxyp9RC5xhvcdudBq3xutZJrhE0Mse4gTHILbGwFwcgDHqNZE6XNYXhSNvL1r1C89o7D2g0pZLtP/AG6ZHbjrTL8DbVaeouq6a3VImgSaA7vH5R6lFBYFc8gjsO/r21sN8+Bl9ttJLPZ6h66jJZkQSKAFfO3eCO49MHg4ONYDbqwWCNLvbrkjPSOk42Ek/MI2eeSe3HtrtT4b9ZR9c2CNrfK8c8LA1tNKUVkJHHrn8H7alqMksOJI6yJdrdEw3XtXGnUtnu1jpailr6d6GkKbpKiOMPuGCjAEeZWDAj2PfSNTtK1JVSXKdqWakgkaNixUIiR+TygZ5BwTgjPtrv7q7oiz3ikLXq1pUq48GbMeZWA5GWI9f6vX765R+K3w86Vt0Vwr+ibjQTR01NNT1FFFUrK8JccbcEkDdjKntg6CmtpIPCnGCfpScVsslysqjjOTXO1otAeSmnErrEk0TEKPKCOSD/fTx0fRCpubCu/WjlqTmOQAna/0kZ4Hpn7ao0Nje7/IyWR5N8lLvkeJR4cxHBGMjnIx30bts9XR3SOkltaJUGLYUZ9o8UDKkhv5QMnj9tINblpMqee9eopfw2tvtdNydjj9KI9SdL1FZby9nqXjFG//AA3n27mxxtJzxgcDudUbPRSVNJL4yOCIl2yRSjxWHLHA9AB99xxojTXirqmrKmeWnVFqwzNk+dlHlcY9AMgAa8WC/l55IJIzHuqVkYE5CyRnKMex5BIP7Dtq+0mMhtkhyKwHtG9tKBPbrtYelSwR1lJUSzb6wojgJPUhVZVcd1DDkH240UNzoq+ip6FE8Kp2ApDGpUuSxUnPbBzn1xntovW1/wA5aXkp7aayWrZoYpIUUlfMNwAJB4ODk5K4IGlqhqK2CWPxYyxl8VRHAwEUO5vPIpOSR5cFT6859NWN7YRDDLVXpmrXKM0eSQevNX7PJJVwNRpTyOlHNI5cODFuxgqORlRgEeuc6mVRJMYZjLIs8pl2B9oZSvlYbeVYMDke2qLyOpgqKGGoeOo3QyCLajOVGFOOOQM5x+deYqV7U0dxrqlYIpJfDTA8Qgscn/qB/Y+w0njAxWkEit0NWYakdPSwTQ1ZjR3JKrwME8nseM9vX3146xi/iklBR2WtWtuVRKhBWA+LUSKuNpbsPYnt2GvVqtlR17XU9qtNKK6up3khgRYjvlz/ADFs4XHqSeO2umPgz8FLZ8PxDeeottwvbonhuw3Q0Z7skYP1MfV/7aJPqy6bAd3foKzeoxGW8yOwrmr4h/Dae3WaDqKjYeNUUm2thKjKtGchl44Yd8ew9dZnBcJIb1bp5paorVxGNV8TksV5DcZOT5gOODga7u+JHw/W439a3aiW+oic1fheWQjPlXHOM88+2uWviZ0dS2mq6toLNSbRRmj6gtQBy6Qqdso3jnnkD01mtK1wwyNv6k5q7vRHf2sQU+cZGO2M0/8A+F/oU3nqSfqe5UcVZR2ZjT080qrIfmmAyT6FVXj7Hv763P4qdSdHdLdPSS9V2+ilqYpP0KeWjUmdAcELwSGHrnjGNZF0D8S7J8M/h1D070lZzWXC4MJ2llURU6yOMyMGP1MQQPTSNU3as6p6mpr11FcY69KGokpVp5HAAlI3EFdwIGBgHP2GTploZNavchtoqrksZ7GEu6+Udz/FQTWxviJNPfKmiit1neoxBS0kRdaiRQSjE+mFHf8AuNC5aauqGq6aKme2wSsjh/FAITZzHj1OQDg++jVe0IaStnppKET4McLM5+khQYhwu4ZGc4JHv30mXO8C51dVS2+vimb5rxnhkCyBWUgEH0IGM4GeTnW4RIdPgAU9P1qhhilupPKP6rp34KWWZqS5V0oJqIKkQwmRskqeSVPBI7DHbTP8RLXBVW2aqqKqKG4UsqvTvKhYRykc8DHm2+o1zt8LfjlcOmxVW262x6qhkqA2+NsShn/pJ4Ppx760zrH42dD9YdP1dFR1EpuTKIjFPEUlh2jAOMcn0yNYbUjK2pNcRjPmyCPyq3j0+SG1R39096y/q3p23TT1dxheWqjEaTxSNTgbMcyxqAMcn+b0+2lS12Kqouq6OjKR0sy1y7JUAMa9mYKO5Ow4x99TdJ3Ongiugq6qVmDOzD5tl3hsYwAOAGHOOORpuqYrZfqTe1DVxVGwLul8JZkyeZQoww29sg7m+2tuiLqEALcORVDKxikIzxXUtnmT5JXd2ZkYkkOBtGOFx9hz/wBtIHXvUlruFJTW8Vc9OsuZ3HDLsU5OftgZzxj01ilJ8YevOlka2VtQlRSu3+7VS0rpJMo45GOGx3GSfvoQJazqKeJqRzJSEyTGNdqDODnJxnbnk7jjA99YtdFkjnIm6CrNJ/EAWLqeKodV11H1Bfv4y0VbI5qNsTRyhgkRUAk+3OCQfQ8c6ILSRpSxRW22vDLTbEjdMZRn5LHf3BA4/OvNHQW2WKkEcB8R53RpaiMIEReVdvZW7jPOMDV9KYUU1c1JUstVVMTFO/nU7FHiblJzjafKONXEa7YwF6VorOxW1cmQZaqMlO3ybxV1NTk7jv8AChCmUDsJME8/cf30z22XqGz2qhS2Xy5QQiNpDSzSgKhwSvOO+RyPbvoBBVUtugkiHhU8SwmP5yWNjLliMjIP089u2NG4Op6R+mKoFqaA0peNWjcFZSpxiMHuD7+nOqnVI5Au+LNa3Qxp927W9/twORnijEnXnxMkho6lLtBIiwRzMPlwqq+7AjI5w3c4PGOdVbl8ffiJS2ue2JSUj1BqiVmEQicQgbQI8+UAYyxPuNK8t+uNVbUqLZK9NvUszscFsDIxkgA4457DVW02F7zHPVVtdExjSQACMsGV9u44JB259efTRrHRbu4AeVAM1Q+0F17PRBo7LJYdx0qpP1/1fc5zV3q4yXCctN4rRwKVPGfDwBxlfXBz30bo+u7GLbFTJReFNT+GsS0nATCZKszZYPgnuCD340xR9N0drzb4rQ1TUxKJ3erj8sqkbAGZSFUhW4XOcgd9Uq/pqgqaKpElOnzTsGaV4CgFOqbFEjgjzE8EYyQM5HbWxttOltVCxnA9O1eczzJKxwOKz293q23i2JWW6F5GWR3cKuwRK/BjU5xtG0EH3yfXQGknpkEtLSVoWF81EciyN4iuR/wzg9ie/oT9tOkXR89N1bPZ/kw1tnhVmjVgURhje2Pq28rgHtp/65sHTlu/h1LR0VsS3LAIKlVjy6SYIIlfGfY5B9saz2s6g1g48VcmrzQ9NfVZhbwtgms4sXSZraeBbZSUqbi0KyRsz5kcZO1OTlWBHbTjY7BcrNVmsH8RpthWCWRWbzwkbo2DD074z5hzoRbKOGFZIpo5WpCJSWBcMrqgwMjlWzgnP2GmWodaSQU9PMRE6LJHKJyBKdu0BRuwD3B78+ura0FtqlsSmP5FDu7O79n9QAuh7p/IiqPVDdbx2S509L15c4JvlJPCiNW0iSKUJDEHtkHaD7jOuLuiKa7dNfEOOxVzSLUSyJF4EyOslQ7Hhd3rnnOeNdo3Va6tkmpZKw00UC+AEPFTJLsBUeEQAQoIb7gn20gdZ9G0FS9BGt3WWrp6ynjldYXSWmUSL3yMrySRjIIPfWdg0S8hZnmxtH8VrtY13RbhFOnxlZOCTjjpyKSOjK1aWBqaOeo+VSaRY3k8paUuVeMg8BVbAH99FLpdKGsrEmkoP94yAlRgho2C4dSD3B9CdNFrtNKl7vFqrIlEFvuUnhfpgK3mJzyfX/XXq99M294lLOq1kLEF45CAVzkEHGcg4/HOp+HHMwlAoEct0Lfw0fg9j0pSjgMlXQVMFRFUeLEyMjnbnaPKSAMbl7H3GO50bsdmkt6pUiqj3zEyqzRkxlR/XjP9scfbV6bpFEqVqpHEcAAqfCXClmGGwMfShx3xnVieRq6f516aKSrqOZKaJSViZuPFY+pxxgfvzqytfDQl34ArMXVvMrCJ+/SinT8sNBd6213ilpvHRgfEhlV4gpTeWTYSM8jAznvnnUN5WCeFFcsYSo2ufNuVhnAIxnjn9tFLT0v1ztWufp5qaARbIx4IAKocbzkeuf8AxoT1BZbjbYJLetIiKlSrx0+eNpbdkt2yTlQBoMl+sz7VNW9vYJDGShyxFUkroah6dKitEq1UbOhj/VkO3jchPC8DBxyM6DXa6T1UnzsEPy9MzFIosh5VUjGFAGAD39hqX5paCiipZaiOdaR3emwdqgvneOMZOW2+xwNWrdbq5bmnixRQU6YDIFLl39VIzkY4GdFSASECqWW+nXIPFfOnOoblT3w3eBrwlQ6EVDxYCGZFCkADHA4zj+2uqOgfjZaLxb4KWoPydUHCtDUOQWYJ5ufTnj351i8FiNDX/IPdaVJVlNZSoSRLGkgXdGFYYzkYLYGOB99fZY4Lo4ljijkqDKREh434yHYcAZ7cf21T+02nNDEJgMjp8q03snp9tr8jW002yXtnoRxXUtVX2650UsMVQj06MhXwzuwOSVJP+Y1xV8Zes6K29fvV0FZHLGAtvmCPlXjckY/zH20RvU3UlgM81iuNdTPMCtVEZTiRducbe2QfTWKIsklRJUVLLM07I++SLxHLZJwecDPp+NUel2UbsZg2fhTeqaPc6DdLHOMgngjpW2WClqI7UjxhXYKY0jyGRnI48rcklR6E8e2gsFxo6CaukmrKKmjEoqFaGLNQu7hVORu2gcA5IGqD3ishsAlSrV3dljRo0MLBsHaCr5HvkjSVJcf4etPHdYGiJfx3qDKHXBHJJHA/H+R1eaPbSWsrTMKf9sdUtrizhtbcnsTxTrfur6ioppZ6GOGGOYsCyzHbJwMkqxIPb9z2xpBlvlVBG15pKJoJBIMU0EgUH3b3AP459dMHS9OOuL/b7FTQxwQUaF5PDOVRM55VRgqc49NPHX3S1mip6l/mXEiRgM0adzgbVOe6gDU9S1MRsEfrWLsy0cZVByaodJW0TW+pUQhmRQ6eI20sUbnBPHrkffVHqujSnrKlZGhjHgJKXdiyFt3csp4Y9s88+g009PRpWRvbEURLOfpcbmfH3znn/TQWtttOlabdUS1DojGLMaAJCxOSzBuVAHA7k541X2Exku8mvT9c09IdEVEOcc/vQq3wUdkvlNTXWhmW118HixxsCAZNu4qoyM4HOMjnnWoUlDZqcWeCjrp6WKOT5hqfbv3Js3hywGQFzkgtz7HSd1FIlx6cgkWnKV1L4T0gEXMZjbszHluPb350z0PUKTmCpqJUZw6OohVlDh4yhxxyVDMB+cZONbrS5AGZO9eQ6pZmIK6jg186k6fbqGFbdI0cFLRCbbLDUFmqmwCJUU8oD6j10rdGpPLaLpR3aCczQuEjjVeJSQdrHHAGO49hrRLXLTRU9PFVRqbdT00cDxGUSEmP6QxxvQrxuJPPr21nj3IUXV1XK9cVpamZNqwSkIRjIfd/Tjj9tB9okH4Yuhwxpr2TMf8Ak0E/u0yUdW38GFdDVkVLhQQELYGAckYOeRwNDo6uvqVqJ6O3FHdPEkkmCYUldrD3zjBwDxqx09YamWvutojnpYqWrlMiTBXO/wBTGQOT37jGBq/WCkoRcPkrUk9LFTkB4eDCVGHKptZlQcZG3ByOdB0iCG5s0f61Ze0l5dWWpSRA4B5H0FLd9sd6c7rvC1LTUkayClXlJFY9nIP1Hv8AjSvRK0gpJkaQIj+HTtASGjQE7Wk92PueMa2eVaS5dIQVSCellp6dDO80Yd343BAo4JA4Y9h3zrF6Sy1NdPXS0onMULePNuTcIwDgEgd8Z9eBo+oW8dqFKDAxWWW4knY7zk0bsVZPDTfwWqlU0RnLqgplUnDZKsucMnc5Y5OBpxpbjFPHcYbAq1NLDSyTSDbtmjVPrlAXnb24Lbcn7aVbRRGNRZ6iEhayFGqHqKlhmNT5doHpnzD7anpqZ7RMIqag+cnnZqZ5mXPjuw8oVe23tnjQoNQaEgZytWVtpwu4yQcGtes3yF16dijnq/lqp4kCmTE6uxXxNm1eWK4wWPPIPGqUoWqqjUUTBzJgSwMmBOwGwgjksQCDnIzpMobtQmyo/gPTXG3NHVTNRghpVB2OgzwGZNwwT2/Gi6VU9zr5LZDQywTU8EUsjxz4yqP4hCsON6xqEGMjJ9daGG6jmUFTxVNc2cltKQ4q9S0ym7Ib3JDS08EBid5IsmSHG3ZsQ9t38pOQcau/Eak6lpkpLpdraKW0eAq0VWUwjRqPKGXBIf8APv30e+EBtvVfXF2lbc1NUrHOYUTKeIh3AckHdg85HJBOtumt6dRx1NruMC1NIf0lEvAbnHrwQfca869prpZLrawyP+1otCu7jSZFuIfeHrXKFNTQJWT0dJWU58UB4o0O9MsAQrbuT7HnkHVel6olo5Gtdys0NJGgkRxHKUwo5HPpgjIA9hox1f8ACufpq9xUNIJKSnz4SzvKxH/FLbnb1GOPLjAA0mdXWq8QR1DT06TmnqYyWhA8V5GJSRue4C4I9sj8aJpVjcWRF1ZNuQ9R/dabVvaex1+D8PfRlJB0PUffFX+rjPbblbrtba0y09yCvAvKCZSAVbfknIO4NnB83tpcvl1ra+5QPNaoKcvWU5jjQksu2Rchtvc8Yz21bju1tulnioKitUT0cgWjhnbDpziLavoSAQe+c868y3SnFGKqtK06wVKyLG+H2tvGW3j1x6emNX99MZF8RDww5FZGwt4mYxNye3xq/wBa0Edl+I98FZRSU9NVSNloWO4lx32/fP8AloUlbUihjargDSrJHH8w4CtJsOGcAc7dm0cjk+nrrT/jvaKOGtlp6CnWtvV0lgp6SMltxJjDb0Zf5lHJJwoB1jE0tdaa42i/08ltr98daTLGHTwmQxY4yCpbnI4zrM6ZcGaPYx5BI/WrWK+NuSjcip626GCpo7fFb/HlovGWRhMVB8U52lvUAEYHoR31v3wV6HtUlwp7lthkYFmqpUwT4jL2IORtDYGfQ65hu1OtAyyRytURfpKJo8oszK2dwx+fXOtD6U+InUnQtTcKnp5vEphndBMniIPL5uO+BgnI9fXTl9C7wFUbBqvkunu5g6j+xXaFNQ2i2NLbVoppaeSQyqZCGQHPp9wfTSt1j8MLF1VSmGChEEsxSocEEIpQkptYfzZzn050v/Df4sUHU9za23R4KOsWmimjKSGNZkkUHcgfsftye+tWtlf4FLDLRuJVEZH6g2umc4fPbB1iXS4s5fNTaOQQQea4r+Jvw1uvTkLVNHSTiBQNkZUtu5J3Akds+h1JaUrLexnlp0UzwLIwfH6kiYACqDyCWwR3JGfTXaEtHSVFJGLnDDU7FMqRSwKyh/6gSD6Ht99Yz8Q/h1NYaee69EUC1tvWWT5inY7zSeQlmC8bgM59ce2tbomtpuCXRwexpDUITJh1rLKmjSrqbZcBXCZZIWlWMyFi4J2HEoG7GQcjvnGgNwoWgoorrXS/LzQmVJgHLEEOSMA8FgMZHB+2jnS8FxuVLS1dsoo5aeKmleEQVBV4YuDIcHBJYqTjuD21JW9AdRVFHHRyUVoamrgXjT55HdZ3bcrlQcLtQ+dicj11sr64tGiMUrAZ6f3SVi89pMs0ecqRQOvro620Q14qomSMK8zjG8buF38ck+msOuKNQdUJAKlhC85aSQ4CbD9GPQDvye341td16T6vNpWht9Za5Pl5mUJBV78ojY8VNoKshzwQc49NZR8QunrjbLAl2r7xb6qWn8PfTUzuSoZsFeVA457n++vPbIQ20jbWzXqOt6z/AJeGKNv/AJpnutsuU1Pb7bBG1VFUy+KmwMyEBMhAy5C88bs4186u6bjnsxqJrghgYoJVgQKN2QVDMM5IwRwfTVL4Z3ethvMENFdoWLRMlLHUQGRWlxwhwy4xkngH21qnUNKz9Hy2mrmmmDTMGmSmUKXZchgDhsFhgYXI5763GmQpJCT3rz3XJnWcZ6dqGfA3pWltFlr7vSUcitVruRSzOqxqcBN/oO5P3Ol/ri8CrrKqlkmB3Pt2tzlR6E+2lGXrTrDoSguFRZXj/h09P5YJiCYpd2SwDY59NInQPXdw6ru1ym6jr2kj34QJDwh9SxAPt66xeq6ZN47T5BFWmgCOW5jRvUVuFuqKK3pU07qarwsxSNkjyld3BPPbkH11Vh8PwxTW3wWd9pjUyHxHwN247sZxnnntoDTdRWiS3xCWqgFC+FLvMqyq2OGHOMfn8a92S70dVKrG7U9OhcwpM0ysseew2f3833wdMxQCG4J9a0kusm+sFjPUZB+VMVSloqIqKZaXaXIiEvibMl8h43Iby+cAjPcaGdOVSU7zUT4aSlcb/BDGYwISdwYHnGThfU6gLRW+OppGvVOTNvibEiCGQ44yCeT9/TQez3qQST2G01EG6uMMCrvTMxBxt8xBAyff01dQTrBKHzWdv1WW2wK1Oh6jn6juc3T3T9Upp62FRKXYF41VeWkXHBIxu74JGdCeqOkL1bvFpxSkSQBGp9uNpjxtO1eDj/l7A62z4cfCnpPoenpLhUXq3teJFZaqZK2IIGJyyRrngYwPudJfXr2/qC43aKkrKeJ6dJg0grEKnBzkHPGRwdVN9rpuJ9oHlFd0CwgkVw5wcZz0xSV0Ve6mutjU9XFMlZE4pYmps7iQeWDehHb99Fqa6QolX40U0sssM9JNDEwVA74CQgnls43EnjI1m09+nstTDdbbeqWNw7qQsy42Kf0ztz9WM5/vq/T9XfxOSkvFqNMtTHUITvqUXDEEFlzznPv/AJaf02drCVgvuN+lE1iWPVbMPMf/AFj/AP0KfbjWUVqsMVealoZaGeOWaJFMnjRyr4bRhO5JO38d9aj0T8PBb7TDfY6Zaa6V9NIatiquiCUDgIeCAQB2xwdZF0LRU/WPVdu6cu15ppoTMZalFqo1jEEQyXxngg4GfXXXaVfSlTTSij6js/yzLiKJqyMPGpAG0Dd9idL+0+pmVUhiPx/esvZwDljXPXxn6OvVLardVR26OorqNkpY6mNgGlUnOcKAABknPtxpOh2w2aOtkvMMdRTSxuzqh82CVZQewx6ng62j4k3bpys6bittT1LQxJBOVMUc6O8qrxg8kKCcfuNYDR3CgNPcKZbrDTfJTkGOWSN45jjltpOBnIz+NK6TOXTDHmriymFvMVPQ1dq4qEUnzFLVbZKpSI1kdlhIAPp9O3BJBJ9PvqjQ9SVVwRqRJlp46eGKGWKpjJ8TwwVcpjuXyDj2xocbhFVVlFZ4Xopkmifez1KHxMJtAKZ2p3JHfRisorJSNbLdb6uKqcFhinqkBRgoBypOA33zqye/FqNueTVp/jDqjl0wQO+R+lXOgeqOoeiOskqrIZwxR2qYpSQhjOCC6v2GP5hyNdWdF/FrpDqqGngesSkufiGBopxgSH1CE8OuMYI5+2udbYtsoY45P4rSyO8TF0lqovEiQsAUyDhySATz240r9dV1nUeDFf4KaqgqvmRJHMm3C4clCDwWbC4HGM6orl1v5eRVxcez0NvZb3fzAdM10R8YKqa3RVM9U6LHvSSFqctI4I4diOAo24B/OshoIrb1VaaMz17eA9OHaCcndAzBhIzyIfEbKhcZzggHjSHU/Em8vRVdFJ1LHXfNtMQlU6u0TMDkLk8+4J/7aqWfqqOmlUyVcKrSxRSxDxhG1QZF2mN3BJIDdxjGtBogbTmZXYFT9/zXn14iSxhl94VeuHS92t9VFWU1ZRXCWokCg+IFk8pBEgB58PHG48d/XRz4m9KVHRFfPY68A0lVSLcYwI1ZAGAJCt/MVfvn00y09wt0VA9oFTaRTpDLC0/ixvjCh8hgQxXBYd++kv4p9S1FXY6CyXyqp6mht9Qk1LVxVSPJ8tJHwh57H1B5GNOatabts9uwx3GRS9nOUYbuD2rQ/ihYlu8vSvXsFveshewpTzwUj7JfCmj2GWPkbnDDOAckdtc/VtX0tNfY7P0ZJeLhbenLXLQ+LcUaOeqmkcM64zwEYYwffTjbvjPTJ0X0/bmulOJrOghUFlfCLIwBPPPBBxoPapbbXV0l9hko1kqJ/HqYo3SGNiWzhtpGMkZzyedZm0g8GYsx4zxVwqtdsdtX7f03VVURqaiFKSOGNGTdMDncePKRwB3xnkjRq5xw2q2pUQeHVuIGlq9iELHGrdt3rnkfbJ76ICr6bFOlTJfKRKiSndGMsyNtfkxAAHk9xk9h30IrquxSWeSGkneJaioaN4kqowjLkFlHPl82T9+2reVldSpIq6s7aO2YSD3h3zRy0StcLVHX19PTNPnEX6ZLLj6cMPTbjn7aYunfiL1v0yksNnqjXwCFoV+akz5c71wW9c5H37azeyXKz0bVdBcLvTSPAAsASYbWUDAyTxyvcD1Gmm23S208bRVF5tqrNEdpM6BWAXjufLj0GsdqO+2uAByK9U0qw0rXdPJu9u/14B+taJU/4gesYII5qm2UsTIfFqTTLkJHjB2K3HORn20mXz/Ex1vcaG4Uz2e2okh+VCLJsdgFHmyO6nuTjvqnd+qLDW0D1oqaCeYQGFgJkAUFe4APPA0gXpKGe6pPG9B4VWiNHKkqqkII+5yBkdhzzqz0+3FwQWiGK899o9I0zTG220+T6dcfDivI+I1bZ+rjPXwBqUn5mSlgcwmQFgzqDjAYEYBA7HW89K9T9L9T9FN1JdYJqJJ1lp5/BhNRDTOGzGVJYeYA+3OTzrDKiy2urhjluVRQmpmURU8ElQm8s4JFR3yAAMFSfXTfdLX0DZaG2W3oXqMSwXKCnuFXTTVCqYSEx4Wc+YGTc3v2B01r0X4Sy8TPm6DBzWRstss+zt3PStAorZ8PZY/4Xa66spPHx8u1NRrGKY7QG2iSRsliMksDg8DA1hPxttdpt1TdbPZribmailzNHUxBJaeoQ5G0JhcnOcHI9tbRbrBT0vVNL05euobbE9TTwTyTirjdYxKvAyG7jjPtpE+IMPR9D1dLaviDU083kSNK231UbmaPnwzuB5TI/wCoaw+n380V0rT5Kd+KuZIldSIzg/Ouapai7WWggr0tlRJ4WJEl27VglUecH0GtV6Z+Jkd+tdHS1c9Q9VTCNZNrnKkcv5s8IQQcY/Gh/WD01r6b+Zr6uiKRSs0qmaMYVTjIUMSzOp9R3GRrOOrZLX8POpYaqz1G+gkgRXijlEjzI6jzd85GcZ/vr017gWrJLF0YVTYNyngy9Aev80Z+LV8qrlFVUEVVTzpEQ0skMARVA5HnAG844J59NL3wbpIpbXdpzKYT44CFSfEkJ9QPXGvnWPUFBU2eOgoKim21MW9h4oBCjnHB7/21d+Ed1s9N0lIlVOxV6tv0xOqmTGPqP21XT3EtyjORj4Vq9PtLKxmVN4bjJPT8q//Z') 0 0 no-repeat; +} diff --git a/node_modules/grunt-contrib-less/test/expected/ieCompatTrue.css b/node_modules/grunt-contrib-less/test/expected/ieCompatTrue.css new file mode 100644 index 000000000..3552ce119 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/ieCompatTrue.css @@ -0,0 +1,5 @@ +body { + width: 288px; + height: 288px; + background: transparent url('include/bob.jpg') 0 0 no-repeat; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual/level2/style3.css b/node_modules/grunt-contrib-less/test/expected/individual/level2/style3.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual/level2/style3.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual/style.css b/node_modules/grunt-contrib-less/test/expected/individual/style.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual/style.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual/style2.css b/node_modules/grunt-contrib-less/test/expected/individual/style2.css new file mode 100644 index 000000000..3eb693199 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual/style2.css @@ -0,0 +1,3 @@ +#header { + background: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual_flatten/style.css b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual_flatten/style2.css b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style2.css new file mode 100644 index 000000000..3eb693199 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style2.css @@ -0,0 +1,3 @@ +#header { + background: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/individual_flatten/style3.css b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style3.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/individual_flatten/style3.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/less.css b/node_modules/grunt-contrib-less/test/expected/less.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/less.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/nomatches.css b/node_modules/grunt-contrib-less/test/expected/nomatches.css new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-less/test/expected/nopaths.css b/node_modules/grunt-contrib-less/test/expected/nopaths.css new file mode 100644 index 000000000..ef8eb9422 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/nopaths.css @@ -0,0 +1,3 @@ +body { + color: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/expected/variablesAsLess.css b/node_modules/grunt-contrib-less/test/expected/variablesAsLess.css new file mode 100644 index 000000000..3eb693199 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/expected/variablesAsLess.css @@ -0,0 +1,3 @@ +#header { + background: #ffffff; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/customFunctions.less b/node_modules/grunt-contrib-less/test/fixtures/customFunctions.less new file mode 100644 index 000000000..ac4a46089 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/customFunctions.less @@ -0,0 +1,5 @@ +.myRule { + background-color: get-color(red); + width: multiple-args(1px, 4px); + background: string-result(3); +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/ieCompat.less b/node_modules/grunt-contrib-less/test/fixtures/ieCompat.less new file mode 100644 index 000000000..20463e6d1 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/ieCompat.less @@ -0,0 +1,5 @@ +body { + width: 288px; + height: 288px; + background: transparent data-uri('include/bob.jpg') 0 0 no-repeat; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/include/bob.jpg b/node_modules/grunt-contrib-less/test/fixtures/include/bob.jpg new file mode 100644 index 000000000..d4e2a4620 Binary files /dev/null and b/node_modules/grunt-contrib-less/test/fixtures/include/bob.jpg differ diff --git a/node_modules/grunt-contrib-less/test/fixtures/include/variables.less b/node_modules/grunt-contrib-less/test/fixtures/include/variables.less new file mode 100644 index 000000000..48a21133d --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/include/variables.less @@ -0,0 +1 @@ +@color: #ffffff; diff --git a/node_modules/grunt-contrib-less/test/fixtures/include/variablesAsLess.css b/node_modules/grunt-contrib-less/test/fixtures/include/variablesAsLess.css new file mode 100644 index 000000000..48a21133d --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/include/variablesAsLess.css @@ -0,0 +1 @@ +@color: #ffffff; diff --git a/node_modules/grunt-contrib-less/test/fixtures/level2/style3.less b/node_modules/grunt-contrib-less/test/fixtures/level2/style3.less new file mode 100644 index 000000000..2a2f0d3b8 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/level2/style3.less @@ -0,0 +1,4 @@ +@import "variables.less"; +body { + color: @color; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/nopaths.less b/node_modules/grunt-contrib-less/test/fixtures/nopaths.less new file mode 100644 index 000000000..dcb229abf --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/nopaths.less @@ -0,0 +1,4 @@ +@import "include/variables.less"; +body { + color: @color; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/style.less b/node_modules/grunt-contrib-less/test/fixtures/style.less new file mode 100644 index 000000000..95ac28a1d --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/style.less @@ -0,0 +1,4 @@ +@import "variables.less"; +body { + color: @color; +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-less/test/fixtures/style2.less b/node_modules/grunt-contrib-less/test/fixtures/style2.less new file mode 100644 index 000000000..8478aa119 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/style2.less @@ -0,0 +1,4 @@ +@import "variables.less"; +#header { + background: @color; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/style3.less b/node_modules/grunt-contrib-less/test/fixtures/style3.less new file mode 100644 index 000000000..b6d23b134 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/style3.less @@ -0,0 +1,4 @@ +#footer { + color: #377; + background: #233; +} diff --git a/node_modules/grunt-contrib-less/test/fixtures/variablesAsLess.less b/node_modules/grunt-contrib-less/test/fixtures/variablesAsLess.less new file mode 100644 index 000000000..97f7ef1bd --- /dev/null +++ b/node_modules/grunt-contrib-less/test/fixtures/variablesAsLess.less @@ -0,0 +1,4 @@ +@import (less) "include/variablesAsLess.css"; +#header { + background: @color; +} diff --git a/node_modules/grunt-contrib-less/test/less_test.js b/node_modules/grunt-contrib-less/test/less_test.js new file mode 100644 index 000000000..577fce400 --- /dev/null +++ b/node_modules/grunt-contrib-less/test/less_test.js @@ -0,0 +1,123 @@ +'use strict'; + +var grunt = require('grunt'); +var fs = require('fs'); + +exports.less = { + compile: function(test) { + test.expect(2); + + var actual = grunt.file.read('tmp/less.css'); + var expected = grunt.file.read('test/expected/less.css'); + test.equal(expected, actual, 'should compile less, with the ability to handle imported files from alternate include paths'); + + actual = grunt.file.read('tmp/concat.css'); + expected = grunt.file.read('test/expected/concat.css'); + test.equal(expected, actual, 'should concat output when passed an array'); + + test.done(); + }, + compress: function(test) { + test.expect(1); + + var actual = grunt.file.read('tmp/compress.css'); + var expected = grunt.file.read('test/expected/compress.css'); + test.equal(expected, actual, 'should compress output when compress option is true'); + + test.done(); + }, + nopaths: function(test) { + test.expect(1); + + var actual = grunt.file.read('tmp/nopaths.css'); + var expected = grunt.file.read('test/expected/nopaths.css'); + test.equal(expected, actual, 'should default paths to the dirname of the less file'); + + test.done(); + }, + cleancss: function(test) { + test.expect(2); + + var actual = grunt.file.read('tmp/cleancss.css'); + var expected = grunt.file.read('test/expected/cleancss.css'); + test.equal(expected, actual, 'should cleancss output when cleancss option is true'); + + actual = grunt.file.read('tmp/cleancssReport.css'); + expected = grunt.file.read('test/expected/cleancssReport.css'); + test.equal(expected, actual, 'should cleancss output when cleancss option is true and concating is enable'); + + test.done(); + }, + ieCompat: function(test) { + test.expect(2); + + var actual = grunt.file.read('tmp/ieCompatFalse.css'); + var expected = grunt.file.read('test/expected/ieCompatFalse.css'); + test.equal(expected, actual, 'should generate data-uris no matter the size when ieCompat option is true'); + + actual = grunt.file.read('tmp/ieCompatTrue.css'); + expected = grunt.file.read('test/expected/ieCompatTrue.css'); + test.equal(expected, actual, 'should generate data-uris only when under the 32KB mark for Internet Explorer 8'); + + test.done(); + }, + variablesAsLess: function(test) { + test.expect(1); + + var actual = grunt.file.read('tmp/variablesAsLess.css'); + var expected = grunt.file.read('test/expected/variablesAsLess.css'); + test.equal(expected, actual, 'should process css files imported less files'); + + test.done(); + }, + sourceMap: function(test) { + test.expect(1); + + var actual = grunt.file.read('tmp/sourceMap.css'); + test.ok(actual.indexOf('/*# sourceMappingURL=') !== -1, 'compiled file should include a source map.'); + + test.done(); + }, + sourceMapFilename: function(test) { + test.expect(1); + + var sourceMap = grunt.file.readJSON('tmp/sourceMapFilename.css.map'); + test.equal(sourceMap.sources[0], 'test/fixtures/style3.less', 'should generate a sourceMap with the less file reference.'); + + test.done(); + }, + sourceMapBasepath: function(test) { + test.expect(1); + + var sourceMap = grunt.file.readJSON('tmp/sourceMapBasepath.css.map'); + test.equal(sourceMap.sources[0], 'style3.less', 'should use the basepath for the less file references in the generated sourceMap.'); + + test.done(); + }, + sourceMapRootpath: function(test) { + test.expect(1); + + var sourceMap = grunt.file.readJSON('tmp/sourceMapRootpath.css.map'); + test.equal(sourceMap.sources[0], 'http://example.org/test/fixtures/style3.less', 'should use the rootpath for the less file references in the generated sourceMap.'); + + test.done(); + }, + sourceMapLessInline: function(test) { + test.expect(1); + + var expected = grunt.file.read('test/fixtures/style3.less'); + var sourceMap = grunt.file.readJSON('tmp/sourceMapLessInline.css.map'); + test.equal(sourceMap.sourcesContent[0], expected, 'should put the less file into the generated sourceMap instead of referencing them.'); + + test.done(); + }, + customFunctions: function(test) { + test.expect(1); + + var actual = grunt.file.read('tmp/customFunctions.css'); + var expected = grunt.file.read('test/expected/customFunctions.css'); + test.equal(expected, actual, 'should execute custom functions'); + + test.done(); + } +}; diff --git a/node_modules/grunt-contrib-uglify/.jshintrc b/node_modules/grunt-contrib-uglify/.jshintrc new file mode 100644 index 000000000..f57a8ff4f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/.jshintrc @@ -0,0 +1,13 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true +} diff --git a/node_modules/grunt-contrib-uglify/.npmignore b/node_modules/grunt-contrib-uglify/.npmignore new file mode 100644 index 000000000..9a1b41abc --- /dev/null +++ b/node_modules/grunt-contrib-uglify/.npmignore @@ -0,0 +1,4 @@ +node_modules +npm-debug.log +tmp +.idea diff --git a/node_modules/grunt-contrib-uglify/.travis.yml b/node_modules/grunt-contrib-uglify/.travis.yml new file mode 100644 index 000000000..57661910e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/AUTHORS b/node_modules/grunt-contrib-uglify/AUTHORS new file mode 100644 index 000000000..ae935c11d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/AUTHORS @@ -0,0 +1,3 @@ +"Cowboy" Ben Alman (http://benalman.com) +Tyler Kellen (http://goingslowly.com) +Jarrod Overson (http://jarrodoverson.com) \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/CHANGELOG b/node_modules/grunt-contrib-uglify/CHANGELOG new file mode 100644 index 000000000..040ebef88 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/CHANGELOG @@ -0,0 +1,61 @@ +v0.2.7: + date: 2013-11-09 + changes: + - prepending banner if sourceMap option not set, addresses #109 +v0.2.6: + date: 2013-11-08 + changes: + - merged 45, 53, 85 (105 by way of duping 53) + - Added support for banners in uglified files with sourcemaps + - Updated docs +v0.2.5: + date: 2013-10-28 + changes: + - Added warning for banners when using sourcemaps +v0.2.4: + date: 2013-09-02 + changes: + - updated sourcemap format via /83 +v0.2.3: + date: 2013-06-10 + changes: + - added footer option +v0.2.2: + date: 2013-05-31 + changes: + - Reverted /56 due to /58 until [chrome/239660](https://code.google.com/p/chromium/issues/detail?id=239660&q=sourcemappingurl&colspec=ID%20Pri%20M%20Iteration%20ReleaseBlock%20Cr%20Status%20Owner%20Summary%20OS%20Modified) [firefox/870361](https://bugzilla.mozilla.org/show_bug.cgi?id=870361) drop +v0.2.1: + date: 2013-05-22 + changes: + - Bumped uglify to ~2.3.5 /55 /40 + - Changed sourcemappingUrl syntax /56 + - Disabled sorting of names for consistent mangling /44 + - Updated docs for sourceMapRoot /47 /25 +v0.2.0: + date: 2013-03-14 + changes: + - No longer report gzip results by default. + - Support `report` option. +v0.1.2: + date: 2013-01-30 + changes: + - Added better error reporting + - Support for dynamic names of multiple sourcemaps +v0.1.1: + date: 2013-02-15 + changes: + - First official release for Grunt 0.4.0. +v0.1.1rc6: + date: 2013-01-18 + changes: + - Updating grunt/gruntplugin dependencies to rc6. + - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. +v0.1.1rc5: + date: 2013-01-09 + changes: + - Updating to work with grunt v0.4.0rc5. + - Switching back to this.files api. +v0.1.0: + date: 2012-11-28 + changes: + - Work in progress, not yet officially released. diff --git a/node_modules/grunt-contrib-uglify/CONTRIBUTING.md b/node_modules/grunt-contrib-uglify/CONTRIBUTING.md new file mode 100644 index 000000000..5d08cc387 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/CONTRIBUTING.md @@ -0,0 +1 @@ +Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project. diff --git a/node_modules/grunt-contrib-uglify/Gruntfile.js b/node_modules/grunt-contrib-uglify/Gruntfile.js new file mode 100644 index 000000000..5b99d2cd1 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/Gruntfile.js @@ -0,0 +1,260 @@ +/* + * grunt-contrib-uglify + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'tasks/**/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + } + }, + + // Before generating any new files, remove any previously-created files. + clean: { + tests: ['tmp'] + }, + + // Configuration to be run (and then tested). + uglify: { + compress: { + files: { + 'tmp/compress.js': ['test/fixtures/src/simple.js'] + }, + options: { + mangle: false + } + }, + compress_mangle: { + files: { + 'tmp/compress_mangle.js': ['test/fixtures/src/simple.js'] + } + }, + compress_mangle_banner: { + files: { + 'tmp/compress_mangle_banner.js': ['test/fixtures/src/simple.js'] + }, + options : { + banner : '// banner without sourcemap\n' + } + }, + no_src: { + files: { + 'tmp/compress_mangle.js': [] + } + }, + compress_mangle_except: { + files: { + 'tmp/compress_mangle_except.js': ['test/fixtures/src/simple.js'] + }, + options: { + mangle: { + except: ['argumentC'] + } + } + }, + compress_mangle_beautify: { + files: { + 'tmp/compress_mangle_beautify.js': ['test/fixtures/src/simple.js'] + }, + options: { + beautify: true + } + }, + enclose: { + files: { + 'tmp/enclose.js': ['test/fixtures/src/simple.js'] + }, + options: { + beautify: true, + compress: false, + enclose: { + 'window.argA': 'paramA', + 'window.argB': 'paramB' + }, + mangle: false + } + }, + multifile: { + files: { + 'tmp/multifile.js': ['test/fixtures/src/simple.js','test/fixtures/src/comments.js'] + }, + options: { + mangle: false + } + }, + compress_mangle_sourcemap: { + files: { + '/dev/null': ['test/fixtures/src/simple.js'] + }, + options: { + sourceMap: 'tmp/compress_mangle_sourcemap' + } + }, + sourcemapin: { + files: { + 'tmp/sourcemapin.js': ['test/fixtures/src/simple2.js'] + }, + options: { + mangle: false, + banner: '// Hello World\n', + sourceMap: 'tmp/sourcemapin', + sourceMapIn: 'test/fixtures/src/simple2.map', + sourceMapRoot: 'http://local.host/js/' + } + }, + sourcemapurl: { + files: { + 'tmp/sourcemapurl.js': ['test/fixtures/src/simple.js'] + }, + options: { + sourceMappingURL: 'js/sourcemapurl.js.map' + } + }, + comments: { + src: 'test/fixtures/src/comments.js', + dest: 'tmp/comments.js', + options: { + mangle: false, + preserveComments: 'some' + } + }, + wrap: { + src: 'test/fixtures/src/simple.js', + dest: 'tmp/wrap.js', + options: { + mangle: false, + wrap: 'testExport' + } + }, + exportAll: { + src: 'test/fixtures/src/simple.js', + dest: 'tmp/exportAll.js', + options: { + mangle: false, + wrap: 'testExport', + exportAll: true + } + }, + sourcemap_prefix: { + files: { + '/dev/null': ['test/fixtures/src/simple.js'] + }, + options: { + sourceMap: 'tmp/sourcemap_prefix', + sourceMapPrefix: 3 + } + }, + multiple_sourcemaps: { + files: { + 'tmp/multiple_sourcemaps1.js': ['test/fixtures/src/simple.js'], + 'tmp/multiple_sourcemaps2.js': ['test/fixtures/src/comments.js'] + }, + options: { + sourceMap: function(dest) { + return dest.replace(/\.js$/,".map"); + }, + sourceMappingURL: function(dest) { + return dest.replace(/\.js$/,".mapurl"); + } + } + }, + sourcemap_in_generator_single_src: { + files: [{ + expand: true, + flatten: true, + src: ['test/fixtures/expected/multiple_sourcemaps*.js'], + dest: 'tmp', + ext: '.min.js' + }], + options: { + sourceMap: function (dest) { return dest.replace(/\.js$/, '') + '.map'; }, + sourceMapIn: function (src) { return src.replace(/\.js$/, '') + '.map'; } + } + }, + sourcemap_in_generator_multi_src: { + src: 'test/fixtures/expected/multiple_sourcemaps*.js', + dest: 'tmp/multiple_sourcemaps_all.min.js', + options: { + sourceMap: function (dest) { return dest.replace(/\.js$/, '') + '.map'; }, + sourceMapIn: function (src) { return src.replace(/\.js$/, '') + '.map'; } + } + } + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'] + } + + }); + + // task that expects its argument (another task) to fail + grunt.registerTask('expectFail', function(){ + var task = this.args.join(':'); + + var done = this.async(); + + function onComplete(error, result, code) { + grunt.log.write("\n > " + result.stdout.split("\n").join("\n > ") + "\n"); + var rv = error ? true : new Error("Task " + task + " unexpectedly passed."); + done(rv); + } + + grunt.util.spawn({ + grunt : true, + args : task + }, onComplete); + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-internal'); + + // Whenever the "test" task is run, first clean the "tmp" dir, then run this + // plugin's task(s), then test the result. + grunt.registerTask('test', [ + 'clean', + 'uglify:compress', + 'uglify:compress_mangle', + 'uglify:compress_mangle_banner', + 'uglify:no_src', + 'uglify:compress_mangle_except', + 'uglify:compress_mangle_beautify', + 'uglify:multifile', + 'uglify:compress_mangle_sourcemap', + 'uglify:sourcemapin', + 'uglify:sourcemapurl', + 'uglify:comments', + 'uglify:wrap', + 'uglify:exportAll', + 'uglify:sourcemap_prefix', + 'uglify:multiple_sourcemaps', + 'uglify:enclose', + 'uglify:sourcemap_in_generator_single_src', + 'expectFail:uglify:sourcemap_in_generator_multi_src', // fail case + 'nodeunit' + ]); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test', 'build-contrib']); + +}; diff --git a/node_modules/grunt-contrib-uglify/LICENSE-MIT b/node_modules/grunt-contrib-uglify/LICENSE-MIT new file mode 100644 index 000000000..7f9d34663 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 "Cowboy" Ben Alman, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-uglify/README.md b/node_modules/grunt-contrib-uglify/README.md new file mode 100644 index 000000000..960fd6004 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/README.md @@ -0,0 +1,386 @@ +# grunt-contrib-uglify v0.2.6 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-uglify.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-uglify) + +> Minify files with UglifyJS. + + + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-contrib-uglify --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-contrib-uglify'); +``` + + + + +## Uglify task +_Run this task with the `grunt uglify` command._ + +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. +### Options + +This task primarily delegates to [UglifyJS2][], so please consider the [UglifyJS documentation][] as required reading for advanced configuration. + +[UglifyJS2]: https://github.com/mishoo/UglifyJS2 +[UglifyJS documentation]: http://lisperator.net/uglifyjs/ + +#### mangle +Type: `Boolean` `Object` +Default: `{}` + +Turn on or off mangling with default options. If an `Object` is specified, it is passed directly to `ast.mangle_names()` *and* `ast.compute_char_frequency()` (mimicking command line behavior). + +#### compress +Type: `Boolean` `Object` +Default: `{}` + +Turn on or off source compression with default options. If an `Object` is specified, it is passed as options to `UglifyJS.Compressor()`. + +#### beautify +Type: `Boolean` `Object` +Default: `false` + +Turns on beautification of the generated source code. An `Object` will be merged and passed with the options sent to `UglifyJS.OutputStream()` + +#### report +Choices: `false` `'min'` `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Uglify is performing, but using `'gzip'` can add 5-10x runtime task execution. + +Example ouput using `'gzip'`: + +``` +Original: 198444 bytes. +Minified: 101615 bytes. +Gzipped: 20084 bytes. +``` + +#### sourceMap +Type: `String` `Function` +Default: `undefined` + +The location to output the sourcemap. If a function is provided, the uglify destination is passed as the argument +and the return value will be used as the sourceMap name. + +#### sourceMapRoot +Type: `String` +Default: `undefined` + +The location where your source files can be found. This sets the sourceRoot field in the source map. + +#### sourceMapIn +Type: `String` `Function` +Default: `undefined` + +The location of an input source map from an earlier compilation, e.g. from CoffeeScript. If a function is provided, the +uglify source is passed as the argument and the return value will be used as the sourceMap name. This only makes sense +when there's one source file. + +#### sourceMappingURL +Type: `String` `Function` +Default: `undefined` + +The location of your sourcemap. Defaults to the location you use for sourceMap, override if you need finer control. Provide +a function to dynamically generate the sourceMappingURL based off the destination. + +#### sourceMapPrefix +Type: `Number` +Default: `undefined` + +The number of directories to drop from the path prefix when declaring files in the source map. + +###### enclose +Type: `Object` +Default: `undefined` + +Wrap all of the code in a closure with a configurable arguments/parameters list. +Each key-value pair in the `enclose` object is effectively an argument-parameter pair. + +#### wrap +Type: `String` +Default: `undefined` + +Wrap all of the code in a closure, an easy way to make sure nothing is leaking. +For variables that need to be public `exports` and `global` variables are made available. +The value of wrap is the global variable exports will be available as. + +#### exportAll +Type: `Boolean` +Default: `false` + +When using `wrap` this will make all global functions and variables available via the export variable. + +#### preserveComments +Type: `Boolean` `String` `Function` +Default: `undefined` +Options: `false` `'all'` `'some'` + +Turn on preservation of comments. + +- `false` will strip all comments +- `'all'` will preserve all comments in code blocks that have not been squashed or dropped +- `'some'` will preserve all comments that start with a bang (`!`) or include a closure compiler style directive (`@preserve` `@license` `@cc_on`) +- `Function` specify your own comment preservation function. You will be passed the current node and the current comment and are expected to return either `true` or `false` + +#### banner +Type: `String` +Default: empty string + +This string will be prepended to the beginning of the minified output. It is processed using [grunt.template.process][], using the default options. + +#### footer +Type: `String` +Default: empty string + +This string will be append to the end of the minified output. It is processed using [grunt.template.process][], using the default options. + +_(Default processing options are explained in the [grunt.template.process][] documentation)_ + +[grunt.template.process]: https://github.com/gruntjs/grunt/wiki/grunt.template#wiki-grunt-template-process + + +### Usage examples + +#### Basic compression + +This configuration will compress and mangle the input files using the default options. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + files: { + 'dest/output.min.js': ['src/input1.js', 'src/input2.js'] + } + } + } +}); +``` + +#### No mangling + +Specify `mangle: false` to prevent changes to your variable and function names. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + mangle: false + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +#### Reserved identifiers + +You can specify identifiers to leave untouched with an `except` array in the `mangle` options. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + mangle: { + except: ['jQuery', 'Backbone'] + } + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +#### Source maps + +Configure basic source map output by specifying a file path for the `sourceMap` option. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + sourceMap: 'path/to/source-map.js' + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +#### Advanced source maps + +You can specify the parameters to pass to `UglifyJS.SourceMap()` which will +allow you to configure advanced settings. + +Refer to the [UglifyJS SourceMap Documentation](http://lisperator.net/uglifyjs/codegen#source-map) for more information. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + sourceMap: 'path/to/source-map.js', + sourceMapRoot: 'http://example.com/path/to/src/', // the location to find your original source + sourceMapIn: 'example/coffeescript-sourcemap.js', // input sourcemap from a previous compilation + }, + files: { + 'dest/output.min.js': ['src/input.js'], + }, + }, + }, +}); +``` + + +#### Beautify + +Specify `beautify: true` to beautify your code for debugging/troubleshooting purposes. +Pass an object to manually configure any other output options passed directly to `UglifyJS.OutputStream()`. + +See [UglifyJS Codegen documentation](http://lisperator.net/uglifyjs/codegen) for more information. + +_Note that manual configuration will require you to explicitly set `beautify: true` if you want traditional, beautified output._ + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + beautify: true + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + }, + my_advanced_target: { + options: { + beautify: { + width: 80, + beautify: true + } + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +#### Banner comments + +In this example, running `grunt uglify:my_target` will prepend a banner created by interpolating the `banner` template string with the config object. Here, those properties are the values imported from the `package.json` file (which are available via the `pkg` config property) plus today's date. + +_Note: you don't have to use an external JSON file. It's also valid to create the `pkg` object inline in the config. That being said, if you already have a JSON file, you might as well reference it._ + +```js +// Project configuration. +grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + uglify: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */' + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +#### Conditional compilation + +You can also enable UglifyJS conditional compilation. This is commonly used to remove debug code blocks for production builds. + +See [UglifyJS global definitions documentation](http://lisperator.net/uglifyjs/compress#global-defs) for more information. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + compress: { + global_defs: { + "DEBUG": false + }, + dead_code: true + } + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` +#### Compiling all files in a folder dynamically + +This configuration will compress and mangle the files dynamically. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + files: [{ + expand: true, + cwd: 'src/js', + src: '**/*.js', + dest: 'dest/js' + }] + } + } +}); +``` + + +## Release History + + * 2013-11-09   v0.2.7   prepending banner if sourceMap option not set, addresses + * 2013-11-08   v0.2.6   merged 45, 53, 85 (105 by way of duping 53) Added support for banners in uglified files with sourcemaps Updated docs + * 2013-10-28   v0.2.5   Added warning for banners when using sourcemaps + * 2013-09-02   v0.2.4   updated sourcemap format via /83 + * 2013-06-10   v0.2.3   added footer option + * 2013-05-31   v0.2.2   Reverted /56 due to /58 until [chrome/239660](https://code.google.com/p/chromium/issues/detail?id=239660&q=sourcemappingurl&colspec=ID%20Pri%20M%20Iteration%20ReleaseBlock%20Cr%20Status%20Owner%20Summary%20OS%20Modified) [firefox/870361](https://bugzilla.mozilla.org/show_bug.cgi?id=870361) drop + * 2013-05-22   v0.2.1   Bumped uglify to ~2.3.5 /55 /40 Changed sourcemappingUrl syntax /56 Disabled sorting of names for consistent mangling /44 Updated docs for sourceMapRoot /47 /25 + * 2013-03-14   v0.2.0   No longer report gzip results by default. Support `report` option. + * 2013-01-30   v0.1.2   Added better error reporting Support for dynamic names of multiple sourcemaps + * 2013-02-15   v0.1.1   First official release for Grunt 0.4.0. + * 2013-01-18   v0.1.1rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. + * 2013-01-09   v0.1.1rc5   Updating to work with grunt v0.4.0rc5. Switching back to this.files api. + * 2012-11-28   v0.1.0   Work in progress, not yet officially released. + +--- + +Task submitted by ["Cowboy" Ben Alman](http://benalman.com) + +*This file was generated on Sat Nov 09 2013 12:42:05.* diff --git a/node_modules/grunt-contrib-uglify/docs/uglify-examples.md b/node_modules/grunt-contrib-uglify/docs/uglify-examples.md new file mode 100644 index 000000000..85fefe18a --- /dev/null +++ b/node_modules/grunt-contrib-uglify/docs/uglify-examples.md @@ -0,0 +1,212 @@ +# Usage examples + +## Basic compression + +This configuration will compress and mangle the input files using the default options. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + files: { + 'dest/output.min.js': ['src/input1.js', 'src/input2.js'] + } + } + } +}); +``` + +## No mangling + +Specify `mangle: false` to prevent changes to your variable and function names. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + mangle: false + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +## Reserved identifiers + +You can specify identifiers to leave untouched with an `except` array in the `mangle` options. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + mangle: { + except: ['jQuery', 'Backbone'] + } + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +## Source maps + +Configure basic source map output by specifying a file path for the `sourceMap` option. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + sourceMap: 'path/to/source-map.js' + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +## Advanced source maps + +You can specify the parameters to pass to `UglifyJS.SourceMap()` which will +allow you to configure advanced settings. + +Refer to the [UglifyJS SourceMap Documentation](http://lisperator.net/uglifyjs/codegen#source-map) for more information. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + sourceMap: 'path/to/source-map.js', + sourceMapRoot: 'http://example.com/path/to/src/', // the location to find your original source + sourceMapIn: 'example/coffeescript-sourcemap.js', // input sourcemap from a previous compilation + }, + files: { + 'dest/output.min.js': ['src/input.js'], + }, + }, + }, +}); +``` + + +## Beautify + +Specify `beautify: true` to beautify your code for debugging/troubleshooting purposes. +Pass an object to manually configure any other output options passed directly to `UglifyJS.OutputStream()`. + +See [UglifyJS Codegen documentation](http://lisperator.net/uglifyjs/codegen) for more information. + +_Note that manual configuration will require you to explicitly set `beautify: true` if you want traditional, beautified output._ + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + options: { + beautify: true + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + }, + my_advanced_target: { + options: { + beautify: { + width: 80, + beautify: true + } + }, + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +## Banner comments + +In this example, running `grunt uglify:my_target` will prepend a banner created by interpolating the `banner` template string with the config object. Here, those properties are the values imported from the `package.json` file (which are available via the `pkg` config property) plus today's date. + +_Note: you don't have to use an external JSON file. It's also valid to create the `pkg` object inline in the config. That being said, if you already have a JSON file, you might as well reference it._ + +```js +// Project configuration. +grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + uglify: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */' + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` + +## Conditional compilation + +You can also enable UglifyJS conditional compilation. This is commonly used to remove debug code blocks for production builds. + +See [UglifyJS global definitions documentation](http://lisperator.net/uglifyjs/compress#global-defs) for more information. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + options: { + compress: { + global_defs: { + "DEBUG": false + }, + dead_code: true + } + }, + my_target: { + files: { + 'dest/output.min.js': ['src/input.js'] + } + } + } +}); +``` +## Compiling all files in a folder dynamically + +This configuration will compress and mangle the files dynamically. + +```js +// Project configuration. +grunt.initConfig({ + uglify: { + my_target: { + files: [{ + expand: true, + cwd: 'src/js', + src: '**/*.js', + dest: 'dest/js' + }] + } + } +}); +``` diff --git a/node_modules/grunt-contrib-uglify/docs/uglify-options.md b/node_modules/grunt-contrib-uglify/docs/uglify-options.md new file mode 100644 index 000000000..7ac0b74b1 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/docs/uglify-options.md @@ -0,0 +1,122 @@ +# Options + +This task primarily delegates to [UglifyJS2][], so please consider the [UglifyJS documentation][] as required reading for advanced configuration. + +[UglifyJS2]: https://github.com/mishoo/UglifyJS2 +[UglifyJS documentation]: http://lisperator.net/uglifyjs/ + +## mangle +Type: `Boolean` `Object` +Default: `{}` + +Turn on or off mangling with default options. If an `Object` is specified, it is passed directly to `ast.mangle_names()` *and* `ast.compute_char_frequency()` (mimicking command line behavior). + +## compress +Type: `Boolean` `Object` +Default: `{}` + +Turn on or off source compression with default options. If an `Object` is specified, it is passed as options to `UglifyJS.Compressor()`. + +## beautify +Type: `Boolean` `Object` +Default: `false` + +Turns on beautification of the generated source code. An `Object` will be merged and passed with the options sent to `UglifyJS.OutputStream()` + +## report +Choices: `false` `'min'` `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Uglify is performing, but using `'gzip'` can add 5-10x runtime task execution. + +Example ouput using `'gzip'`: + +``` +Original: 198444 bytes. +Minified: 101615 bytes. +Gzipped: 20084 bytes. +``` + +## sourceMap +Type: `String` `Function` +Default: `undefined` + +The location to output the sourcemap. If a function is provided, the uglify destination is passed as the argument +and the return value will be used as the sourceMap name. + +## sourceMapRoot +Type: `String` +Default: `undefined` + +The location where your source files can be found. This sets the sourceRoot field in the source map. + +## sourceMapIn +Type: `String` `Function` +Default: `undefined` + +The location of an input source map from an earlier compilation, e.g. from CoffeeScript. If a function is provided, the +uglify source is passed as the argument and the return value will be used as the sourceMap name. This only makes sense +when there's one source file. + +## sourceMappingURL +Type: `String` `Function` +Default: `undefined` + +The location of your sourcemap. Defaults to the location you use for sourceMap, override if you need finer control. Provide +a function to dynamically generate the sourceMappingURL based off the destination. + +## sourceMapPrefix +Type: `Number` +Default: `undefined` + +The number of directories to drop from the path prefix when declaring files in the source map. + +#### enclose +Type: `Object` +Default: `undefined` + +Wrap all of the code in a closure with a configurable arguments/parameters list. +Each key-value pair in the `enclose` object is effectively an argument-parameter pair. + +## wrap +Type: `String` +Default: `undefined` + +Wrap all of the code in a closure, an easy way to make sure nothing is leaking. +For variables that need to be public `exports` and `global` variables are made available. +The value of wrap is the global variable exports will be available as. + +## exportAll +Type: `Boolean` +Default: `false` + +When using `wrap` this will make all global functions and variables available via the export variable. + +## preserveComments +Type: `Boolean` `String` `Function` +Default: `undefined` +Options: `false` `'all'` `'some'` + +Turn on preservation of comments. + +- `false` will strip all comments +- `'all'` will preserve all comments in code blocks that have not been squashed or dropped +- `'some'` will preserve all comments that start with a bang (`!`) or include a closure compiler style directive (`@preserve` `@license` `@cc_on`) +- `Function` specify your own comment preservation function. You will be passed the current node and the current comment and are expected to return either `true` or `false` + +## banner +Type: `String` +Default: empty string + +This string will be prepended to the beginning of the minified output. It is processed using [grunt.template.process][], using the default options. + +## footer +Type: `String` +Default: empty string + +This string will be append to the end of the minified output. It is processed using [grunt.template.process][], using the default options. + +_(Default processing options are explained in the [grunt.template.process][] documentation)_ + +[grunt.template.process]: https://github.com/gruntjs/grunt/wiki/grunt.template#wiki-grunt-template-process + diff --git a/node_modules/grunt-contrib-uglify/docs/uglify-overview.md b/node_modules/grunt-contrib-uglify/docs/uglify-overview.md new file mode 100644 index 000000000..f0c452b99 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/docs/uglify-overview.md @@ -0,0 +1 @@ +Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide. \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/.bin/uglifyjs b/node_modules/grunt-contrib-uglify/node_modules/.bin/uglifyjs new file mode 120000 index 000000000..fef3468b6 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.gitattributes b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.gitattributes new file mode 100644 index 000000000..176a458f9 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.jshintrc b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.jshintrc new file mode 100644 index 000000000..e0cc7bbe8 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.jshintrc @@ -0,0 +1,14 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true, + "es5": true +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.npmignore new file mode 100644 index 000000000..5cb6bfd4d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.travis.yml b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.travis.yml new file mode 100644 index 000000000..f2c257a22 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_install: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/AUTHORS b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/AUTHORS new file mode 100644 index 000000000..5de1a921c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/AUTHORS @@ -0,0 +1,4 @@ +Tyler Kellen (http://goingslowly.com/) +Chris Talkington (http://christalkington.com/) +Larry Davis (http://lazd.net/) +Sindre Sorhus (http://sindresorhus.com) diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/CHANGELOG b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/CHANGELOG new file mode 100644 index 000000000..f1e4c303c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/CHANGELOG @@ -0,0 +1,47 @@ +v0.6.1: + date: 2013-03-24 + changes: + - Add formatForType option +v0.6.0: + date: 2013-03-14 + changes: + - Change API/reportying style for minMaxInfo +v0.5.3: + date: 2013-02-23 + changes: + - use MIT licensed zlib-browserify instead of unlicensed gzip-js +v0.5.2: + date: 2013-01-24 + changes: + - add minMaxGzip & minMaxInfo. +v0.5.0: + date: 2012-12-05 + changes: + - remove findBasePath, buildIndividualDest and isIndividualDest. + - remove options and normalizeMultiTaskFiles. + - remove node v0.6 and grunt v0.3 support. +v0.4.0: + date: 2012-11-20 + changes: + - findBasePath returns '' if passed false. + - Added stripPath. +v0.3.1: + date: 2012-10-29 + changes: + - Tweaked findBasePath to handle single dot differently. + - Start testing with Travis. + - Docs cleanup. +v0.3.0: + date: 2012-09-24 + changes: + - Added findBasePath, buildIndividualDest, isIndividualDest, optsToArgs. + - Refactored tests. + - Automatically parse templates in options. +v0.2.1: + date: 2012-09-14 + changes: + - Added non-destuctive namespace declarations. +v0.2.0: + date: 2012-09-10 + changes: + - Refactored from grunt-contrib into individual repo. diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/Gruntfile.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/Gruntfile.js new file mode 100644 index 000000000..6e602bba7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/Gruntfile.js @@ -0,0 +1,60 @@ +/* + * grunt-lib-contrib + * http://gruntjs.com/ + * + * Copyright (c) 2012 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +module.exports = function(grunt) { + 'use strict'; + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'lib/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + } + }, + + test_vars: { + source: 'source/' + }, + + test_task: { + options: { + param: 'task', + param2: 'task', + template: '<%= test_vars.source %>', + data: { + template: ['<%= test_vars.source %>'] + } + }, + target: { + options: { + param: 'target' + } + } + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'] + } + }); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + + // Whenever the "test" task is run, then test the result. + grunt.registerTask('test', ['nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test']); +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/LICENSE-MIT b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/LICENSE-MIT new file mode 100644 index 000000000..358b067ad --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Tyler Kellen, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/README.md b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/README.md new file mode 100644 index 000000000..88116eb48 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/README.md @@ -0,0 +1,65 @@ +# grunt-lib-contrib [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-lib-contrib.png?branch=master)](http://travis-ci.org/gruntjs/grunt-lib-contrib) + +> Common functionality shared across grunt-contrib tasks. + +The purpose of grunt-lib-contrib is to explore solutions to common problems task writers encounter, and to ease the upgrade path for contrib tasks. + +**These APIs should be considered highly unstable. Depend on them at your own risk!** + +_Over time, some of the functionality provided here may be incorporated directly into grunt for mainstream use. Until then, you may require `grunt-lib-contrib` as a dependency in your projects, but be very careful to specify an exact version number instead of a range, as backwards-incompatible changes are likely to be introduced._ + +### Helper Functions + +#### getNamespaceDeclaration(ns) + +This helper is used to build JS namespace declarations. + +#### optsToArgs(options) + +Convert an object to an array of CLI arguments, which can be used with `child_process.spawn()`. + +```js +// Example +{ + fooBar: 'a', // ['--foo-bar', 'a'] + fooBar: 1, // ['--foo-bar', '1'] + fooBar: true, // ['--foo-bar'] + fooBar: false, // + fooBar: ['a', 'b'] // ['--foo-bar', 'a', '--foo-bar', 'b'] +} +``` + +#### stripPath(pth, strip) + +Strip a path from a path. normalize both paths for best results. + +#### minMaxInfo(min, max, report) + +Helper for logging compressed, uncompressed and gzipped sizes of strings. + +#### report +Choices: `false`, `'min'`, `'gzip'` +Default: `false` + +Either do not report anything, report only minification result, or report minification and gzip results. + +**Important** Including `'gzip'` results can make this task 5-10x slower depending on the size of the file. + + +```js +var max = grunt.file.read('max.js'); +var min = minify(max); +minMaxInfo(min, max, 'gzip'); +``` + +Would print: + +``` +Original: 495 bytes. +Minified: 396 bytes. +Gzipped: 36 bytes. +``` + +-- + +*Lib submitted by [Tyler Kellen](https://goingslowly.com/).* \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/lib/contrib.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/lib/contrib.js new file mode 100644 index 000000000..9dcf9455a --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/lib/contrib.js @@ -0,0 +1,111 @@ +/* + * grunt-lib-contrib + * http://gruntjs.com/ + * + * Copyright (c) 2012 Tyler Kellen, contributors + * Licensed under the MIT license. + */ + +exports.init = function(grunt) { + 'use strict'; + + var exports = {}; + + var path = require('path'); + + exports.getNamespaceDeclaration = function(ns) { + var output = []; + var curPath = 'this'; + if (ns !== 'this') { + var nsParts = ns.split('.'); + nsParts.forEach(function(curPart, index) { + if (curPart !== 'this') { + curPath += '[' + JSON.stringify(curPart) + ']'; + output.push(curPath + ' = ' + curPath + ' || {};'); + } + }); + } + + return { + namespace: curPath, + declaration: output.join('\n') + }; + }; + + // Convert an object to an array of CLI arguments + exports.optsToArgs = function(options) { + var args = []; + + Object.keys(options).forEach(function(flag) { + var val = options[flag]; + + flag = flag.replace(/[A-Z]/g, function(match) { + return '-' + match.toLowerCase(); + }); + + if (val === true) { + args.push('--' + flag); + } + + if (grunt.util._.isString(val)) { + args.push('--' + flag, val); + } + + if (grunt.util._.isNumber(val)) { + args.push('--' + flag, '' + val); + } + + if (grunt.util._.isArray(val)) { + val.forEach(function(arrVal) { + args.push('--' + flag, arrVal); + }); + } + }); + + return args; + }; + + // Strip a path from a path. normalize both paths for best results. + exports.stripPath = function(pth, strip) { + if (strip && strip.length >= 1) { + strip = path.normalize(strip); + pth = path.normalize(pth); + pth = grunt.util._(pth).strRight(strip); + pth = grunt.util._(pth).ltrim(path.sep); + } + + return pth; + }; + + // Log min and max info + function gzipSize(src) { + return src ? require('zlib-browserify').gzipSync(src).length : 0; + } + exports.minMaxInfo = function(min, max, report) { + if (report === 'min' || report === 'gzip') { + grunt.log.writeln('Original: ' + String(max.length).green + ' bytes.'); + grunt.log.writeln('Minified: ' + String(min.length).green + ' bytes.'); + } + if (report === 'gzip') { + // Note this option is pretty slow so it is not enabled by default + grunt.log.write('Gzipped: '); + grunt.log.writeln(String(gzipSize(min)).green + ' bytes.'); + } + }; + + exports.formatForType = function(string, type, namespace, filename) { + namespace = namespace || false; + + if (type === 'amd' && namespace === false) { + string = 'return ' + string; + } else if (type === 'commonjs' && namespace === false) { + string = 'module.exports = ' + string; + } else if (type === 'amd' && namespace !== false || type === 'commonjs' && namespace !== false || type === 'js' && namespace !== false) { + string = namespace+'['+JSON.stringify(filename)+'] = '+string+';'; + } + + return string; + }; + + return exports; +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js new file mode 100644 index 000000000..66740432b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/index.js @@ -0,0 +1,43 @@ +const Zlib = module.exports = require('./zlib'); + +// the least I can do is make error messages for the rest of the node.js/zlib api. +// (thanks, dominictarr) +function error () { + var m = [].slice.call(arguments).join(' ') + throw new Error([ + m, + 'we accept pull requests', + 'http://github.com/brianloveswords/zlib-browserify' + ].join('\n')) +} + +;['createGzip' +, 'createGunzip' +, 'createDeflate' +, 'createDeflateRaw' +, 'createInflate' +, 'createInflateRaw' +, 'createUnzip' +, 'Gzip' +, 'Gunzip' +, 'Inflate' +, 'InflateRaw' +, 'Deflate' +, 'DeflateRaw' +, 'Unzip' +, 'inflateRaw' +, 'deflateRaw'].forEach(function (name) { + Zlib[name] = function () { + error('sorry,', name, 'is not implemented yet') + } +}); + +const _deflate = Zlib.deflate; +const _gzip = Zlib.gzip; + +Zlib.deflate = function deflate(stringOrBuffer, callback) { + return _deflate(Buffer(stringOrBuffer), callback); +}; +Zlib.gzip = function gzip(stringOrBuffer, callback) { + return _gzip(Buffer(stringOrBuffer), callback); +}; \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json new file mode 100644 index 000000000..3d13d8335 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/package.json @@ -0,0 +1,40 @@ +{ + "name": "zlib-browserify", + "version": "0.0.1", + "description": "Wrapper for zlib.js to allow for browserifyication", + "main": "index.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.3" + }, + "scripts": { + "test": "./node_modules/tap test/*.test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/zlib-browserify.git" + }, + "keywords": [ + "zlib", + "browserify" + ], + "author": { + "name": "Brian J. Brennan" + }, + "license": "MIT", + "gitHead": "4be9419f0e8e9dec9629c8a538b33a4efd7df17b", + "readmeFilename": "readme.md", + "readme": "Zlib in yo' browser.\n", + "bugs": { + "url": "https://github.com/brianloveswords/zlib-browserify/issues" + }, + "_id": "zlib-browserify@0.0.1", + "dist": { + "shasum": "f8882b91bd8aa91b5e5a532425309da9f5c0d878" + }, + "_from": "zlib-browserify@0.0.1", + "_resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md new file mode 100644 index 000000000..ca4a5eeaa --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/readme.md @@ -0,0 +1 @@ +Zlib in yo' browser. diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js new file mode 100644 index 000000000..5b7a3ce39 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/test/zlib.test.js @@ -0,0 +1,65 @@ +const test = require('tap').test; +const zlibA = require('zlib'); +const zlibB = require('..'); +const crypto = require('crypto'); + +test('zlibA.deflate -> zlibB.inflate', function (t) { + const expect = crypto.randomBytes(1024); + zlibA.deflate(expect, function (err, cmpA) { + zlibB.inflate(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.deflate -> zlibA.inflate', function (t) { + const expect = crypto.randomBytes(1024); + zlibB.deflate(expect, function (err, cmpA) { + zlibA.inflate(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.deflate -> zlibA.inflate (string)', function (t) { + const expect = 'ohaihihihihihihihihihihihihihihihi'; + zlibB.deflate(expect, function (err, cmpA) { + zlibA.inflate(cmpA, function (err, result) { + t.same(result.toString(), expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibA.gzip -> zlibB.gunzip', function (t) { + const expect = crypto.randomBytes(1024); + zlibA.gzip(expect, function (err, cmpA) { + zlibB.gunzip(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.gzip -> zlibA.gunzip', function (t) { + const expect = crypto.randomBytes(1024); + zlibB.gzip(expect, function (err, cmpA) { + zlibA.gunzip(cmpA, function (err, result) { + t.same(result, expect, 'should match'); + t.end(); + }); + }); +}); + +test('zlibB.gzip -> zlibA.gunzip', function (t) { + const expect = 'lololololoollolololoololololololololololololololololololololol'; + zlibB.gzip(expect, function (err, cmpA) { + zlibA.gunzip(cmpA, function (err, result) { + t.same(result.toString(), expect, 'should match'); + t.end(); + }); + }); +}); + diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js new file mode 100644 index 000000000..a9ea566d3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/node_modules/zlib-browserify/zlib.js @@ -0,0 +1,55 @@ +/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */ +(function() {'use strict';function m(c){throw c;}var r=void 0,u=!0;var B="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function aa(c){if("string"===typeof c){var a=c.split(""),b,e;b=0;for(e=a.length;b>>0;c=a}for(var f=1,d=0,g=c.length,h,j=0;0>>0};function I(c,a){this.index="number"===typeof a?a:0;this.n=0;this.buffer=c instanceof(B?Uint8Array:Array)?c:new (B?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&m(Error("invalid index"));this.buffer.length<=this.index&&this.f()}I.prototype.f=function(){var c=this.buffer,a,b=c.length,e=new (B?Uint8Array:Array)(b<<1);if(B)e.set(c);else for(a=0;a>>8&255]<<16|K[c>>>16&255]<<8|K[c>>>24&255])>>32-a:K[c]>>8-a);if(8>a+d)g=g<>a-h-1&1,8===++d&&(d=0,e[f++]=K[g],g=0,f===e.length&&(e=this.f()));e[f]=g;this.buffer=e;this.n=d;this.index=f};I.prototype.finish=function(){var c=this.buffer,a=this.index,b;0Q;++Q){for(var R=Q,ga=R,ha=7,R=R>>>1;R;R>>>=1)ga<<=1,ga|=R&1,--ha;ba[Q]=(ga<>>0}var K=ba;var S={k:function(c,a,b){return S.update(c,0,a,b)},update:function(c,a,b,e){for(var f=S.L,d="number"===typeof b?b:b=0,g="number"===typeof e?e:c.length,a=a^4294967295,d=g&7;d--;++b)a=a>>>8^f[(a^c[b])&255];for(d=g>>3;d--;b+=8)a=a>>>8^f[(a^c[b])&255],a=a>>>8^f[(a^c[b+1])&255],a=a>>>8^f[(a^c[b+2])&255],a=a>>>8^f[(a^c[b+3])&255],a=a>>>8^f[(a^c[b+4])&255],a=a>>>8^f[(a^c[b+5])&255],a=a>>>8^f[(a^c[b+6])&255],a=a>>>8^f[(a^c[b+7])&255];return(a^4294967295)>>>0}},ia=S,ja,ka=[0,1996959894,3993919788,2567524794, +124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304, +3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486, +2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580, +2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221, +2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863, +817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];ja=B?new Uint32Array(ka):ka;ia.L=ja;function na(){};function oa(c){this.buffer=new (B?Uint16Array:Array)(2*c);this.length=0}oa.prototype.getParent=function(c){return 2*((c-2)/4|0)};oa.prototype.push=function(c,a){var b,e,f=this.buffer,d;b=this.length;f[this.length++]=a;for(f[this.length++]=c;0f[e])d=f[b],f[b]=f[e],f[e]=d,d=f[b+1],f[b+1]=f[e+1],f[e+1]=d,b=e;else break;return this.length}; +oa.prototype.pop=function(){var c,a,b=this.buffer,e,f,d;a=b[0];c=b[1];this.length-=2;b[0]=b[this.length];b[1]=b[this.length+1];for(d=0;;){f=2*d+2;if(f>=this.length)break;f+2b[f]&&(f+=2);if(b[f]>b[d])e=b[d],b[d]=b[f],b[f]=e,e=b[d+1],b[d+1]=b[f+1],b[f+1]=e;else break;d=f}return{index:c,value:a,length:this.length}};function T(c){var a=c.length,b=0,e=Number.POSITIVE_INFINITY,f,d,g,h,j,i,q,l,k;for(l=0;lb&&(b=c[l]),c[l]>=1;for(k=i;kU;U++)switch(u){case 143>=U:sa.push([U+48,8]);break;case 255>=U:sa.push([U-144+400,9]);break;case 279>=U:sa.push([U-256+0,7]);break;case 287>=U:sa.push([U-280+192,8]);break;default:m("invalid literal: "+U)} +pa.prototype.h=function(){var c,a,b,e,f=this.input;switch(this.l){case 0:b=0;for(e=f.length;b>>8&255;k[p++]=i&255;k[p++]=i>>>8&255;if(B)k.set(d,p),p+=d.length,k=k.subarray(0,p);else{q=0;for(l=d.length;qz)for(;0z?z:138,H>z-3&&H=H?(L[J++]=17,L[J++]=H-3,O[17]++):(L[J++]=18,L[J++]=H-11,O[18]++),z-=H;else if(L[J++]=M[y],O[M[y]]++,z--,3>z)for(;0z?z:6,H>z-3&&HG;G++)va[G]=la[ca[G]];for(D=19;4=c:return[265,c-11,1];case 14>=c:return[266,c-13,1];case 16>=c:return[267,c-15,1];case 18>=c:return[268,c-17,1];case 22>=c:return[269,c-19,2];case 26>=c:return[270,c-23,2];case 30>=c:return[271,c-27,2];case 34>=c:return[272,c- +31,2];case 42>=c:return[273,c-35,3];case 50>=c:return[274,c-43,3];case 58>=c:return[275,c-51,3];case 66>=c:return[276,c-59,3];case 82>=c:return[277,c-67,4];case 98>=c:return[278,c-83,4];case 114>=c:return[279,c-99,4];case 130>=c:return[280,c-115,4];case 162>=c:return[281,c-131,5];case 194>=c:return[282,c-163,5];case 226>=c:return[283,c-195,5];case 257>=c:return[284,c-227,5];case 258===c:return[285,c-258,0];default:m("invalid length: "+c)}}var Ba=[],Aa,Ca; +for(Aa=3;258>=Aa;Aa++)Ca=za(),Ba[Aa]=Ca[2]<<24|Ca[1]<<16|Ca[0];var Da=B?new Uint32Array(Ba):Ba; +function ta(c,a){function b(a,c){var b=a.N,d=[],e=0,f;f=Da[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(u){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b- +65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>= +b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:m("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,i;h=0;for(i=d.length;h=d;)v[d++]=0;for(d=0;29>=d;)x[d++]=0}v[256]=1;e=0;for(f=a.length;e=f){l&&b(l,-1);d=0;for(g=f-e;ds&&e+sn&&(C=A,n=s);if(258===s)break}q=new xa(n,e-C);l?l.length2*k[n-1]+p[n]&&(k[n]=2*k[n-1]+p[n]),v[n]=Array(k[n]),x[n]=Array(k[n]);for(C=0;Ch[C]?(v[n][s]=E,x[n][s]=l,D+=2): +(v[n][s]=h[C],x[n][s]=C,++C);F[n]=0;1===p[n]&&b(n)}j=t;i=0;for(q=g.length;i>>=1}return a};function Ea(c,a){this.input=c;this.a=new (B?Uint8Array:Array)(32768);this.l=Fa.u;var b={},e;if((a||!(a={}))&&"number"===typeof a.compressionType)this.l=a.compressionType;for(e in a)b[e]=a[e];b.outputBuffer=this.a;this.H=new pa(this.input,b)}var Fa=ra; +Ea.prototype.h=function(){var c,a,b,e,f,d,g,h=0;g=this.a;c=Ga;switch(c){case Ga:a=Math.LOG2E*Math.log(32768)-8;break;default:m(Error("invalid compression method"))}b=a<<4|c;g[h++]=b;switch(c){case Ga:switch(this.l){case Fa.NONE:f=0;break;case Fa.K:f=1;break;case Fa.u:f=2;break;default:m(Error("unsupported compression type"))}break;default:m(Error("invalid compression method"))}e=f<<6|0;g[h++]=e|31-(256*b+e)%31;d=aa(this.input);this.H.b=h;g=this.H.h();h=g.length;B&&(g=new Uint8Array(g.buffer),g.length<= +h+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,h+4));g[h++]=d>>24&255;g[h++]=d>>16&255;g[h++]=d>>8&255;g[h++]=d&255;return g};function Ha(c,a){this.input=c;this.b=this.c=0;this.g={};a&&(a.flags&&(this.g=a.flags),"string"===typeof a.filename&&(this.filename=a.filename),"string"===typeof a.comment&&(this.comment=a.comment),a.deflateOptions&&(this.m=a.deflateOptions));this.m||(this.m={})} +Ha.prototype.h=function(){var c,a,b,e,f,d,g,h,j=new (B?Uint8Array:Array)(32768),i=0,q=this.input,l=this.c,k=this.filename,p=this.comment;j[i++]=31;j[i++]=139;j[i++]=8;c=0;this.g.fname&&(c|=Ia);this.g.fcomment&&(c|=Ja);this.g.fhcrc&&(c|=Ka);j[i++]=c;a=(Date.now?Date.now():+new Date)/1E3|0;j[i++]=a&255;j[i++]=a>>>8&255;j[i++]=a>>>16&255;j[i++]=a>>>24&255;j[i++]=0;j[i++]=Ya;if(this.g.fname!==r){g=0;for(h=k.length;g>>8&255),j[i++]=d&255;j[i++]=0}if(this.g.comment){g= +0;for(h=p.length;g>>8&255),j[i++]=d&255;j[i++]=0}this.g.fhcrc&&(b=S.k(j,0,i)&65535,j[i++]=b&255,j[i++]=b>>>8&255);this.m.outputBuffer=j;this.m.outputIndex=i;f=new pa(q,this.m);j=f.h();i=f.b;B&&(i+8>j.buffer.byteLength?(this.a=new Uint8Array(i+8),this.a.set(new Uint8Array(j.buffer)),j=this.a):j=new Uint8Array(j.buffer));e=S.k(q);j[i++]=e&255;j[i++]=e>>>8&255;j[i++]=e>>>16&255;j[i++]=e>>>24&255;h=q.length;j[i++]=h&255;j[i++]=h>>>8&255;j[i++]=h>>>16&255;j[i++]= +h>>>24&255;this.c=l;B&&i>>=1;switch(c){case 0:var a=this.input,b=this.c,e=this.a,f=this.b,d=r,g=r,h=r,j=e.length,i=r;this.e=this.j=0;d=a[b++];d===r&&m(Error("invalid uncompressed block header: LEN (first byte)"));g=d;d=a[b++];d===r&&m(Error("invalid uncompressed block header: LEN (second byte)"));g|=d<<8;d=a[b++];d===r&&m(Error("invalid uncompressed block header: NLEN (first byte)"));h=d;d=a[b++];d===r&&m(Error("invalid uncompressed block header: NLEN (second byte)"));h|= +d<<8;g===~h&&m(Error("invalid uncompressed block header: length verify"));b+g>a.length&&m(Error("input buffer is broken"));switch(this.r){case $a:for(;f+g>e.length;){i=j-f;g-=i;if(B)e.set(a.subarray(b,b+i),f),f+=i,b+=i;else for(;i--;)e[f++]=a[b++];this.b=f;e=this.f();f=this.b}break;case Za:for(;f+g>e.length;)e=this.f({B:2});break;default:m(Error("invalid inflate mode"))}if(B)e.set(a.subarray(b,b+g),f),f+=g,b+=g;else for(;g--;)e[f++]=a[b++];this.c=b;this.b=f;this.a=e;break;case 1:this.s(ab,bb);break; +case 2:cb(this);break;default:m(Error("unknown BTYPE: "+c))}}return this.z()}; +var db=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],eb=B?new Uint16Array(db):db,fb=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],gb=B?new Uint16Array(fb):fb,hb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],ib=B?new Uint8Array(hb):hb,jb=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],kb=B?new Uint16Array(jb):jb,lb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10, +10,11,11,12,12,13,13],mb=B?new Uint8Array(lb):lb,nb=new (B?Uint8Array:Array)(288),Y,ob;Y=0;for(ob=nb.length;Y=Y?8:255>=Y?9:279>=Y?7:8;var ab=T(nb),pb=new (B?Uint8Array:Array)(30),qb,rb;qb=0;for(rb=pb.length;qb>>a;c.e=e-a;c.c=d;return g} +function sb(c,a){for(var b=c.j,e=c.e,f=c.input,d=c.c,g=a[0],h=a[1],j,i,q;e>>16;c.j=b>>q;c.e=e-q;c.c=d;return i&65535} +function cb(c){function a(a,b,c){var d,f,e,g;for(g=0;gd)e>=f&&(this.b=e,b=this.f(),e=this.b),b[e++]=d;else{g=d-257;j=gb[g];0=f&&(this.b=e,b=this.f(),e=this.b);for(;j--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e}; +W.prototype.Q=function(c,a){var b=this.a,e=this.b;this.A=c;for(var f=b.length,d,g,h,j;256!==(d=sb(this,c));)if(256>d)e>=f&&(b=this.f(),f=b.length),b[e++]=d;else{g=d-257;j=gb[g];0f&&(b=this.f(),f=b.length);for(;j--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e}; +W.prototype.f=function(){var c=new (B?Uint8Array:Array)(this.b-32768),a=this.b-32768,b,e,f=this.a;if(B)c.set(f.subarray(32768,c.length));else{b=0;for(e=c.length;bb;++b)f[b]=f[a+b];this.b=32768;return f}; +W.prototype.R=function(c){var a,b=this.input.length/this.c+1|0,e,f,d,g=this.input,h=this.a;c&&("number"===typeof c.B&&(b=c.B),"number"===typeof c.M&&(b+=c.M));2>b?(e=(g.length-this.c)/this.A[2],d=258*(e/2)|0,f=da&&(this.a.length=a),c=this.a);return this.buffer=c};function tb(c){this.input=c;this.c=0;this.member=[]} +tb.prototype.i=function(){for(var c=this.input.length;this.c>>0;S.k(f)!==q&&m(Error("invalid CRC-32 checksum: 0x"+S.k(f).toString(16)+" / 0x"+q.toString(16))); +a.Y=b=(l[k++]|l[k++]<<8|l[k++]<<16|l[k++]<<24)>>>0;(f.length&4294967295)!==b&&m(Error("invalid input size: "+(f.length&4294967295)+" / "+b));this.member.push(a);this.c=k}var p=this.member,t,v,x=0,F=0,w;t=0;for(v=p.length;t>>0,b!==aa(a)&&m(Error("invalid adler-32 checksum")));return a};exports.deflate=vb;exports.deflateSync=wb;exports.inflate=xb;exports.inflateSync=yb;exports.gzip=zb;exports.gzipSync=Ab;exports.gunzip=Bb;exports.gunzipSync=Cb;function vb(c,a,b){process.nextTick(function(){var e,f;try{f=wb(c,b)}catch(d){e=d}a(e,f)})}function wb(c,a){var b;b=(new Ea(c)).h();a||(a={});return a.G?b:Db(b)}function xb(c,a,b){process.nextTick(function(){var e,f;try{f=yb(c,b)}catch(d){e=d}a(e,f)})} +function yb(c,a){var b;c.subarray=c.slice;b=(new ub(c)).i();a||(a={});return a.noBuffer?b:Db(b)}function zb(c,a,b){process.nextTick(function(){var e,f;try{f=Ab(c,b)}catch(d){e=d}a(e,f)})}function Ab(c,a){var b;c.subarray=c.slice;b=(new Ha(c)).h();a||(a={});return a.G?b:Db(b)}function Bb(c,a,b){process.nextTick(function(){var e,f;try{f=Cb(c,b)}catch(d){e=d}a(e,f)})}function Cb(c,a){var b;c.subarray=c.slice;b=(new tb(c)).i();a||(a={});return a.G?b:Db(b)} +function Db(c){var a=new Buffer(c.length),b,e;b=0;for(e=c.length;b=$?8:255>=$?9:279>=$?7:8;T(Jb);var Lb=new (B?Uint8Array:Array)(30),Mb,Nb;Mb=0;for(Nb=Lb.length;Mb= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-nodeunit": "~0.1.2", + "grunt": "~0.4.0" + }, + "main": "lib/contrib", + "dependencies": { + "zlib-browserify": "0.0.1" + }, + "contributors": [ + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com/" + }, + { + "name": "Chris Talkington", + "url": "http://christalkington.com/" + }, + { + "name": "Larry Davis", + "url": "http://lazd.net/" + }, + { + "name": "Sindre Sorhus", + "url": "http://sindresorhus.com" + } + ], + "readme": "# grunt-lib-contrib [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-lib-contrib.png?branch=master)](http://travis-ci.org/gruntjs/grunt-lib-contrib)\n\n> Common functionality shared across grunt-contrib tasks.\n\nThe purpose of grunt-lib-contrib is to explore solutions to common problems task writers encounter, and to ease the upgrade path for contrib tasks.\n\n**These APIs should be considered highly unstable. Depend on them at your own risk!**\n\n_Over time, some of the functionality provided here may be incorporated directly into grunt for mainstream use. Until then, you may require `grunt-lib-contrib` as a dependency in your projects, but be very careful to specify an exact version number instead of a range, as backwards-incompatible changes are likely to be introduced._\n\n### Helper Functions\n\n#### getNamespaceDeclaration(ns)\n\nThis helper is used to build JS namespace declarations.\n\n#### optsToArgs(options)\n\nConvert an object to an array of CLI arguments, which can be used with `child_process.spawn()`.\n\n```js\n// Example\n{\n fooBar: 'a', // ['--foo-bar', 'a']\n fooBar: 1, // ['--foo-bar', '1']\n fooBar: true, // ['--foo-bar']\n fooBar: false, //\n fooBar: ['a', 'b'] // ['--foo-bar', 'a', '--foo-bar', 'b']\n}\n```\n\n#### stripPath(pth, strip)\n\nStrip a path from a path. normalize both paths for best results.\n\n#### minMaxInfo(min, max, report)\n\nHelper for logging compressed, uncompressed and gzipped sizes of strings.\n\n#### report\nChoices: `false`, `'min'`, `'gzip'`\nDefault: `false`\n\nEither do not report anything, report only minification result, or report minification and gzip results.\n\n**Important** Including `'gzip'` results can make this task 5-10x slower depending on the size of the file.\n\n\n```js\nvar max = grunt.file.read('max.js');\nvar min = minify(max);\nminMaxInfo(min, max, 'gzip');\n```\n\nWould print:\n\n```\nOriginal: 495 bytes.\nMinified: 396 bytes.\nGzipped: 36 bytes.\n```\n\n--\n\n*Lib submitted by [Tyler Kellen](https://goingslowly.com/).*", + "readmeFilename": "README.md", + "_id": "grunt-lib-contrib@0.6.1", + "dist": { + "shasum": "42925d314e0307f033f8b65c60d9c4cc595723cb" + }, + "_from": "grunt-lib-contrib@~0.6.1", + "_resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/test/lib_test.js b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/test/lib_test.js new file mode 100644 index 000000000..446864af2 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/grunt-lib-contrib/test/lib_test.js @@ -0,0 +1,233 @@ +var grunt = require('grunt'); +var helper = require('../lib/contrib.js').init(grunt); + +exports.lib = { + getNamespaceDeclaration: function(test) { + 'use strict'; + + test.expect(10); + + // Both test should result in this[JST] + var expected = { + namespace: 'this["JST"]', + declaration: 'this["JST"] = this["JST"] || {};' + }; + + var actual = helper.getNamespaceDeclaration("this.JST"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + actual = helper.getNamespaceDeclaration("JST"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + // Templates should be declared globally if this provided + expected = { + namespace: "this", + declaration: "" + }; + + actual = helper.getNamespaceDeclaration("this"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + // Nested namespace declaration + expected = { + namespace: 'this["GUI"]["Templates"]["Main"]', + declaration: 'this["GUI"] = this["GUI"] || {};\n' + + 'this["GUI"]["Templates"] = this["GUI"]["Templates"] || {};\n' + + 'this["GUI"]["Templates"]["Main"] = this["GUI"]["Templates"]["Main"] || {};' + }; + + actual = helper.getNamespaceDeclaration("GUI.Templates.Main"); + test.equal(expected.namespace, actual.namespace, 'namespace incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration incorrect'); + + // Namespace that contains square brackets + expected = { + namespace: 'this["main"]["[test]"]["[test2]"]', + declaration: 'this["main"] = this["main"] || {};\n' + + 'this["main"]["[test]"] = this["main"]["[test]"] || {};\n' + + 'this["main"]["[test]"]["[test2]"] = this["main"]["[test]"]["[test2]"] || {};' + }; + + actual = helper.getNamespaceDeclaration("main.[test].[test2]"); + test.equal(expected.namespace, actual.namespace, 'namespace with square brackets incorrect'); + test.equal(expected.declaration, actual.declaration, 'namespace declaration with square brackets incorrect'); + + test.done(); + }, + optsToArgs: function(test) { + 'use strict'; + + test.expect(1); + + var fixture = { + key: 'a', + key2: 1, + key3: true, + key4: false, + key5: ['a', 'b'] + }; + var expected = ['--key', 'a', '--key2', '1', '--key3', '--key5', 'a', '--key5', 'b' ].toString(); + var actual = helper.optsToArgs(fixture).toString(); + test.equal(expected, actual, 'should convert object to array of CLI arguments'); + + test.done(); + }, + stripPath: function(test) { + 'use strict'; + var path = require('path'); + + test.expect(4); + + var actual = helper.stripPath('path1/path2', 'path1'); + var expected = 'path2'; + test.equal(expected, actual, 'should strip path from a directory path and trim it.'); + + actual = helper.stripPath('path1/path2/path3/path4', 'path1/path2'); + expected = path.normalize('path3/path4'); + test.equal(expected, actual, 'should strip path from a directory path and trim it. (deep)'); + + actual = helper.stripPath('path1/file.ext', 'path1'); + expected = 'file.ext'; + test.equal(expected, actual, 'should strip path from a file path and trim it.'); + + actual = helper.stripPath('path1/path2/path3/path4/file.ext', 'path1/path2'); + expected = path.normalize('path3/path4/file.ext'); + test.equal(expected, actual, 'should strip path from a file path and trim it. (deep)'); + + test.done(); + }, + minMaxInfo: function(test) { + 'use strict'; + test.expect(3); + + var max = new Array(100).join('blah '); + var min = max.replace(/\s+/g, ''); + + var actual; + var expected; + + grunt.util.hooker.hook(grunt.log, 'writeln', { + pre: function(result) { + actual += grunt.log.uncolor(result) + grunt.util.linefeed; + return grunt.util.hooker.preempt(); + } + }); + + grunt.util.hooker.hook(grunt.log, 'write', { + pre: function(result) { + actual += grunt.log.uncolor(result); + return grunt.util.hooker.preempt(); + } + }); + + + // No reporting option + actual = ''; + expected = ''; + + helper.minMaxInfo(min, max); + test.equal(expected, actual, 'should not have reported min and max info.'); + + // Report minification results + actual = ''; + expected = [ + 'Original: 495 bytes.', + 'Minified: 396 bytes.' + ].join(grunt.util.linefeed) + grunt.util.linefeed; + + helper.minMaxInfo(min, max, 'min'); + test.equal(expected, actual, 'should have logged min and max info.'); + + // Report minification and gzip results + actual = ''; + expected = [ + 'Original: 495 bytes.', + 'Minified: 396 bytes.', + 'Gzipped: 36 bytes.' + ].join(grunt.util.linefeed) + grunt.util.linefeed; + + helper.minMaxInfo(min, max, 'gzip'); + test.equal(expected, actual, 'should have logged min, max, gzip info.'); + + grunt.util.hooker.unhook(grunt.log, 'writeln'); + grunt.util.hooker.unhook(grunt.log, 'write'); + test.done(); + }, + formatToType: { + amd: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'amd', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to amd with namespace'); + + actual = helper.formatForType(string, 'amd'); + expected = "return function () { }"; + test.equal(expected, actual, 'should format string to amd'); + + test.done(); + }, + commonjs: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'commonjs', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to commonjs with namespace'); + + actual = helper.formatForType(string, 'commonjs'); + expected = "module.exports = function () { }"; + test.equal(expected, actual, 'should format string to commonjs'); + + test.done(); + }, + js: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'js', 'JST', 'test'); + var expected = 'JST["test"] = function () { };'; + test.equal(expected, actual, 'should format string to js with namespace'); + + actual = helper.formatForType(string, 'js'); + expected = 'function () { }'; + test.equal(expected, actual, 'should format string to js'); + + test.done(); + }, + html: function(test) { + + 'use strict'; + + test.expect(2); + + var string = function () { }; + + var actual = helper.formatForType(string, 'html', 'JST', 'test'); + var expected = 'function () { }'; + test.equal(expected, actual, 'should format string to html with namespace'); + + actual = helper.formatForType(string, 'html'); + expected = 'function () { }'; + test.equal(expected, actual, 'should format string to html'); + + test.done(); + } + } +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.npmignore new file mode 100644 index 000000000..94fceeb20 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.travis.yml b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.travis.yml new file mode 100644 index 000000000..d95912721 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.4" + - "0.6" + - "0.8" + - "0.10" + - "0.11" diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/LICENSE new file mode 100644 index 000000000..dd7706f0c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/LICENSE @@ -0,0 +1,29 @@ +UglifyJS is released under the BSD license: + +Copyright 2012-2013 (c) Mihai Bazon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/README.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/README.md new file mode 100644 index 000000000..f2f2f2128 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/README.md @@ -0,0 +1,633 @@ +UglifyJS 2 +========== +[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2) + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + +``` + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //# + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + --screw-ie8 Pass this flag if you don't care about full compliance + with Internet Explorer 6-8 quirks (by default UglifyJS + will try to be IE-proof). [boolean] + --expr Parse a single expression, rather than a program (for + parsing JSON) [boolean] + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. You can also + specify -p relative, which will make UglifyJS figure out + itself the relative paths between original sources, the + source map and the output file. [string] + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + -e, --enclose Embed everything in a big function, with a configurable + parameter/argument list. [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --preamble Preamble to prepend to the output. You can use this to + insert a comment, for example for licensing information. + This will not be parsed, but the source map will adjust + for its presence. + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] +``` + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). The following +(comma-separated) options are supported: + +- `sort` — to assign shorter names to most frequently used variables. This + saves a few hundred bytes on jQuery before gzip, but the output is + _bigger_ after gzip (and seems to happen for other libraries I tried it + on) therefore it's not enabled by default. + +- `toplevel` — mangle names declared in the toplevel scope (disabled by + default). + +- `eval` — mangle names visible in scopes where `eval` or `when` are used + (disabled by default). + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +- `sequences` -- join consecutive simple statements using the comma operator + +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` + +- `dead_code` -- remove unreachable code + +- `drop_debugger` -- remove `debugger;` statements + +- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) + +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions + +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. + +- `evaluate` -- attempt to evaluate constant expressions + +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` + +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition + +- `unused` -- drop unreferenced functions and variables + +- `hoist_funs` -- hoist function declarations + +- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` + by default because it seems to increase the size of the output in general) + +- `if_return` -- optimizations for if/return and if/continue + +- `join_vars` -- join consecutive `var` statements + +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` + +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +- `negate_iife` -- negate "Immediately-Called Function Expressions" + where the return value is discarded, to avoid the parens that the + code generator would insert. + +- `pure_getters` -- the default is `false`. If you pass `true` for + this, UglifyJS will assume that object property access + (e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects. + +- `pure_funcs` -- default `null`. You can pass an array of names and + UglifyJS will assume that those functions do not produce side + effects. DANGER: will not check if the name is redefined in scope. + An example case here, for instance `var q = Math.floor(a/b)`. If + variable `q` is not used elsewhere, UglifyJS will drop it, but will + still keep the `Math.floor(a/b)`, not knowing what it does. You can + pass `pure_funcs: [ 'Math.floor' ]` to let it know that this + function won't produce any side effect, in which case the whole + statement would get discarded. The current implementation adds some + overhead (compression will be slower). + +### The `unsafe` option + +It enables some transformations that *might* break code logic in certain +contrived cases, but should be fine for most code. You might want to try it +on your own code, it should reduce the minified size. Here's what happens +when this flag is on: + +- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` +- `new Object()` → `{}` +- `String(exp)` or `exp.toString()` → `"" + exp` +- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` +- `typeof foo == "undefined"` → `foo === void 0` +- `void 0` → `undefined` (if there is a variable named "undefined" in + scope; we do it because the variable name will be mangled, typically + reduced to a single character). + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: +```javascript +if (DEBUG) { + console.log("debug stuff"); +} +``` + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: +```javascript +const DEBUG = false; +const PRODUCTION = true; +// etc. +``` + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; +var P_RELATIVE = ARGS.p && ARGS.p == "relative"; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +async.eachLimit(files, 1, function (file, cb) { + read_whole_file(file, function (err, code) { + if (err) { + sys.error("ERROR: can't read file: " + file); + process.exit(1); + } + if (ARGS.p != null) { + if (P_RELATIVE) { + file = path.relative(path.dirname(ARGS.source_map), file); + } else { + var p = parseInt(ARGS.p, 10); + if (!isNaN(p)) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + } + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + try { + TOPLEVEL = UglifyJS.parse(code, { + filename : file, + toplevel : TOPLEVEL, + expression : ARGS.expr, + }); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col); + sys.error(ex.message); + sys.error(ex.stack); + process.exit(1); + } + throw ex; + } + }; + }); + cb(); + }); +}, function () { + if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); + }); + + if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); + } + + if (ARGS.enclose) { + var arg_parameter_list = ARGS.enclose; + if (arg_parameter_list === true) { + arg_parameter_list = []; + } + else if (!(arg_parameter_list instanceof Array)) { + arg_parameter_list = [arg_parameter_list]; + } + TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); + } + + var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); + } + + if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); + } + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); + } + + if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); + }); + time_it("generate", function(){ + TOPLEVEL.print(output); + }); + + output = output.get(); + + if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + var source_map_url = ARGS.source_map_url || ( + P_RELATIVE + ? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map) + : ARGS.source_map + ); + output += "\n//# sourceMappingURL=" + source_map_url; + } + + if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); + } else { + sys.print(output); + sys.error("\n"); + } + + if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } + } +}); + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x, { expression: true }); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_Binary) { + var name = node.print_to_string({ beautify: false }).replace(/-/g, "_"); + ret[name] = true; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename, cb) { + if (filename == "-") { + var chunks = []; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }).on('end', function () { + cb(null, chunks.join("")); + }); + process.openStdin(); + } else { + fs.readFile(filename, "utf-8", cb); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/ast.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/ast.js new file mode 100644 index 000000000..0fa48e28e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,990 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_IterationStatement = DEFNODE("IterationStatement", null, { + $documentation: "Internal class. All loops inherit from it." +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_IterationStatement); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_IterationStatement); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_IterationStatement); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + + args.push(split[0]); + parameters.push(split[1]); + }); + + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function. The `name` property is always null." +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LoopControl*] a list of nodes referring to this label" + }, + initialize: function() { + this.references = []; + this.thedef = this; + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + has_directive: function(type) { + return this.find_parent(AST_Scope).has_directive(type); + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } else for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch || x instanceof AST_IterationStatement) + return x; + } + } +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/compress.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/compress.js new file mode 100644 index 000000000..f44277cd7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,2267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : false, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + pure_getters : false, + pure_funcs : null, + negate_iife : !false_by_default, + screw_ie8 : false, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + //node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + node.drop_unused(this); + descend(node, this); + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + + if (compressor.option("negate_iife")) { + negate_iifes(statements, compressor); + } + + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + function negate_iifes(statements, compressor) { + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) { + stat.body = (function transform(thing) { + return thing.transform(new TreeTransformer(function(node){ + if (node instanceof AST_Call && node.expression instanceof AST_Function) { + return make_node(AST_UnaryPrefix, node, { + operator: "!", + expression: node + }); + } + else if (node instanceof AST_Call) { + node.expression = transform(node.expression); + } + else if (node instanceof AST_Seq) { + node.car = transform(node.car); + } + else if (node instanceof AST_Conditional) { + var expr = transform(node.condition); + if (expr !== node.condition) { + // it has been negated, reverse + node.condition = expr; + var tmp = node.consequent; + node.consequent = node.alternative; + node.alternative = tmp; + } + } + return node; + })); + })(stat.body); + } + }); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; if + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original or a replacement node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(compressor); + return [ best_of(make_node_from_constant(compressor, val, this), this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + throw def; + }); + function ev(node, compressor) { + if (!compressor) throw new Error("Compressor must be passed"); + + return node._eval(compressor); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(compressor){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e, compressor); + case "typeof": + // Function would be evaluated to an array and so typeof would + // incorrectly return 'object'. Hence making is a special case. + if (e instanceof AST_Function) return typeof function(){}; + + e = ev(e, compressor); + + // typeof returns "object" or "function" on different platforms + // so cannot evaluate reliably + if (e instanceof RegExp) throw def; + + return typeof e; + case "void": return void ev(e, compressor); + case "~": return ~ev(e, compressor); + case "-": + e = ev(e, compressor); + if (e === 0) throw def; + return -e; + case "+": return +ev(e, compressor); + } + throw def; + }); + def(AST_Binary, function(c){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left, c) && ev(right, c); + case "||" : return ev(left, c) || ev(right, c); + case "|" : return ev(left, c) | ev(right, c); + case "&" : return ev(left, c) & ev(right, c); + case "^" : return ev(left, c) ^ ev(right, c); + case "+" : return ev(left, c) + ev(right, c); + case "*" : return ev(left, c) * ev(right, c); + case "/" : return ev(left, c) / ev(right, c); + case "%" : return ev(left, c) % ev(right, c); + case "-" : return ev(left, c) - ev(right, c); + case "<<" : return ev(left, c) << ev(right, c); + case ">>" : return ev(left, c) >> ev(right, c); + case ">>>" : return ev(left, c) >>> ev(right, c); + case "==" : return ev(left, c) == ev(right, c); + case "===" : return ev(left, c) === ev(right, c); + case "!=" : return ev(left, c) != ev(right, c); + case "!==" : return ev(left, c) !== ev(right, c); + case "<" : return ev(left, c) < ev(right, c); + case "<=" : return ev(left, c) <= ev(right, c); + case ">" : return ev(left, c) > ev(right, c); + case ">=" : return ev(left, c) >= ev(right, c); + case "in" : return ev(left, c) in ev(right, c); + case "instanceof" : return ev(left, c) instanceof ev(right, c); + } + throw def; + }); + def(AST_Conditional, function(compressor){ + return ev(this.condition, compressor) + ? ev(this.consequent, compressor) + : ev(this.alternative, compressor); + }); + def(AST_SymbolRef, function(compressor){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init, compressor); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(compressor){ return true }); + + def(AST_EmptyStatement, function(compressor){ return false }); + def(AST_Constant, function(compressor){ return false }); + def(AST_This, function(compressor){ return false }); + + def(AST_Call, function(compressor){ + var pure = compressor.option("pure_funcs"); + if (!pure) return true; + return pure.indexOf(this.expression.print_to_string()) < 0; + }); + + def(AST_Block, function(compressor){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects(compressor)) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(compressor){ + return this.body.has_side_effects(compressor); + }); + def(AST_Defun, function(compressor){ return true }); + def(AST_Function, function(compressor){ return false }); + def(AST_Binary, function(compressor){ + return this.left.has_side_effects(compressor) + || this.right.has_side_effects(compressor); + }); + def(AST_Assign, function(compressor){ return true }); + def(AST_Conditional, function(compressor){ + return this.condition.has_side_effects(compressor) + || this.consequent.has_side_effects(compressor) + || this.alternative.has_side_effects(compressor); + }); + def(AST_Unary, function(compressor){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(compressor); + }); + def(AST_SymbolRef, function(compressor){ return false }); + def(AST_Object, function(compressor){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects(compressor)) + return true; + return false; + }); + def(AST_ObjectProperty, function(compressor){ + return this.value.has_side_effects(compressor); + }); + def(AST_Array, function(compressor){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects(compressor)) + return true; + return false; + }); + def(AST_Dot, function(compressor){ + if (!compressor.option("pure_getters")) return true; + return this.expression.has_side_effects(compressor); + }); + def(AST_Sub, function(compressor){ + if (!compressor.option("pure_getters")) return true; + return this.expression.has_side_effects(compressor) + || this.property.has_side_effects(compressor); + }); + def(AST_PropAccess, function(compressor){ + return !compressor.option("pure_getters"); + }); + def(AST_Seq, function(compressor){ + return this.car.has_side_effects(compressor) + || this.cdr.has_side_effects(compressor); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects(compressor)) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects(compressor)) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For) { + descend(node, this); + + if (node.init instanceof AST_BlockStatement) { + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects(compressor)) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for(;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }).transform(compressor); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + if (self.args.length <= 1) return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }).transform(compressor); + break; + case "Number": + if (self.args.length == 0) return make_node(AST_Number, self, { + value: 0 + }); + if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { + expression: self.args[0], + operator: "+" + }).transform(compressor); + case "Boolean": + if (self.args.length == 0) return make_node(AST_False, self); + if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { + expression: make_node(AST_UnaryPrefix, null, { + expression: self.args[0], + operator: "!" + }), + operator: "!" + }).transform(compressor); + break; + case "Function": + if (all(self.args, function(x){ return x instanceof AST_String })) { + // quite a corner-case, but we can handle it: + // https://github.com/mishoo/UglifyJS2/issues/203 + // if the code argument is a constant, then we can minify it. + try { + var code = "(function(" + self.args.slice(0, -1).map(function(arg){ + return arg.value; + }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; + var ast = parse(code); + ast.figure_out_scope(); + var comp = new Compressor(compressor.options); + ast = ast.transform(comp); + ast.figure_out_scope(); + ast.mangle_names(); + var fun; + try { + ast.walk(new TreeWalker(function(node){ + if (node instanceof AST_Lambda) { + fun = node; + throw ast; + } + })); + } catch(ex) { + if (ex !== ast) throw ex; + }; + var args = fun.argnames.map(function(arg, i){ + return make_node(AST_String, self.args[i], { + value: arg.print_to_string() + }); + }); + var code = OutputStream(); + AST_BlockStatement.prototype._codegen.call(fun, fun, code); + code = code.toString().replace(/^\{|\}$/g, ""); + args.push(make_node(AST_String, self.args[self.args.length - 1], { + value: code + })); + self.args = args; + return self; + } catch(ex) { + if (ex instanceof JS_Parse_Error) { + compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); + compressor.warn(ex.toString()); + } else { + console.log(ex); + throw ex; + } + } + } + break; + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: { + var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1]; + if (separator == null) break EXIT; // not a constant + var elements = exp.expression.elements.reduce(function(a, el){ + el = el.evaluate(compressor); + if (a.length == 0 || el.length == 1) { + a.push(el); + } else { + var last = a[a.length - 1]; + if (last.length == 2) { + // it's a constant + var val = "" + last[1] + separator + el[1]; + a[a.length - 1] = [ make_node_from_constant(compressor, val, last[0]), val ]; + } else { + a.push(el); + } + } + return a; + }, []); + if (elements.length == 0) return make_node(AST_String, self, { value: "" }); + if (elements.length == 1) return elements[0][0]; + if (separator == "") { + var first; + if (elements[0][0] instanceof AST_String + || elements[1][0] instanceof AST_String) { + first = elements.shift()[0]; + } else { + first = make_node(AST_String, self, { value: "" }); + } + return elements.reduce(function(prev, el){ + return make_node(AST_Binary, el[0], { + operator : "+", + left : prev, + right : el[0], + }); + }, first).transform(compressor); + } + // need this awkward cloning to not affect original element + // best_of will decide which one to get through. + var node = self.clone(); + node.expression = node.expression.clone(); + node.expression.expression = node.expression.expression.clone(); + node.expression.expression.elements = elements.map(function(el){ + return el[0]; + }); + return best_of(self, node); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self.evaluate(compressor)[0]; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects(compressor)) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects(compressor) + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects(compressor) + && !self.cdr.has_side_effects(compressor) + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + function has_side_effects_or_prop_access(node, compressor) { + var save_pure_getters = compressor.option("pure_getters"); + compressor.options.pure_getters = false; + var ret = node.has_side_effects(compressor); + compressor.options.pure_getters = save_pure_getters; + return ret; + } + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && this instanceof AST_Assign + && !has_side_effects_or_prop_access(this.left, compressor)) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + var reverse = compressor.has_directive("use asm") ? noop + : function(op, force) { + if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + // if right is a constant, whatever side effects the + // left side might have could not influence the + // result. hence, force switch. + + if (!(self.left instanceof AST_Binary + && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { + reverse(null, true); + } + } + if (/^[!=]==?$/.test(self.operator)) { + if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) { + if (self.right.consequent instanceof AST_SymbolRef + && self.right.consequent.definition() === self.left.definition()) { + if (/^==/.test(self.operator)) return self.right.condition; + if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor); + } + if (self.right.alternative instanceof AST_SymbolRef + && self.right.alternative.definition() === self.left.definition()) { + if (/^==/.test(self.operator)) return self.right.condition.negate(compressor); + if (/^!=/.test(self.operator)) return self.right.condition; + } + } + if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) { + if (self.left.consequent instanceof AST_SymbolRef + && self.left.consequent.definition() === self.right.definition()) { + if (/^==/.test(self.operator)) return self.left.condition; + if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor); + } + if (self.left.alternative instanceof AST_SymbolRef + && self.left.alternative.definition() === self.right.definition()) { + if (/^==/.test(self.operator)) return self.left.condition.negate(compressor); + if (/^!=/.test(self.operator)) return self.left.condition; + } + } + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.right = self.right.expression; + self.left = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } else if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.right instanceof AST_Number) { + return make_node(AST_Binary, self, { + left: self.left.left, + operator: "+", + right: make_node(AST_String, self.right, { + value: String(self.left.right.value) + }) + }); + } + if (compressor.option("evaluate")) { + if (self.operator == "+") { + if (self.left instanceof AST_Constant + && self.right instanceof AST_Binary + && self.right.operator == "+" + && self.right.left instanceof AST_Constant + && self.right.is_string(compressor)) { + self = make_node(AST_Binary, self, { + operator: "+", + left: make_node(AST_String, null, { + value: "" + self.left.getValue() + self.right.left.getValue(), + start: self.left.start, + end: self.right.left.end + }), + right: self.right.right + }); + } + if (self.right instanceof AST_Constant + && self.left instanceof AST_Binary + && self.left.operator == "+" + && self.left.right instanceof AST_Constant + && self.left.is_string(compressor)) { + self = make_node(AST_Binary, self, { + operator: "+", + left: self.left.left, + right: make_node(AST_String, null, { + value: "" + self.left.right.getValue() + self.right.getValue(), + start: self.left.right.start, + end: self.right.end + }) + }); + } + if (self.left instanceof AST_Binary + && self.left.operator == "+" + && self.left.is_string(compressor) + && self.left.right instanceof AST_Constant + && self.right instanceof AST_Binary + && self.right.operator == "+" + && self.right.left instanceof AST_Constant + && self.right.is_string(compressor)) { + self = make_node(AST_Binary, self, { + operator: "+", + left: make_node(AST_Binary, self.left, { + operator: "+", + left: self.left.left, + right: make_node(AST_String, null, { + value: "" + self.left.right.getValue() + self.right.left.getValue(), + start: self.left.right.start, + end: self.right.left.end + }) + }), + right: self.right.right + }); + } + } + } + // x * (y * z) ==> x * y * z + if (self.right instanceof AST_Binary + && self.right.operator == self.operator + && (self.operator == "*" || self.operator == "&&" || self.operator == "||")) + { + self.left = make_node(AST_Binary, self.left, { + operator : self.operator, + left : self.left, + right : self.right.left + }); + self.right = self.right.right; + return self.transform(compressor); + } + return self.evaluate(compressor)[0]; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/mozilla-ast.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 000000000..d79509422 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix + : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }); + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/output.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/output.js new file mode 100644 index 000000000..37e30c0ef --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1255 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false, + screw_ie8 : false, + preamble : null, + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\x00"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name, true); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + if (options.preamble) { + print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n")); + } + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + function doit() { + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + } + stream.push_node(self); + if (force_parens || self.needs_parens(stream)) { + stream.with_parens(doit); + } else { + doit(); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before || []; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && self.value + && self.value.start.comments_before + && self.value.start.comments_before.length > 0) { + comments = comments.concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (/comment[134]/.test(c.type)) { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right)) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(), p1; + if (p instanceof AST_New && p.expression === this) + return true; + + // workaround for Safari bug. + // https://bugs.webkit.org/show_bug.cgi?id=123506 + return this.expression instanceof AST_Function + && p instanceof AST_PropAccess + && p.expression === this + && (p1 = output.parent(1)) instanceof AST_Assign + && p1.left === p; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && !output.option("screw_ie8")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + if (self.operator == "<" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "!" + && self.right.expression instanceof AST_UnaryPrefix + && self.right.expression.operator == "--") { + // space is mandatory to avoid outputting ") && S.newline_before) { + forward(3); + return skip_line_comment("comment4"); + } + } + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0; i < a.length; ++i) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = i + 1; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null, + expression : false, + html5_comments : true, + }); + + var S = { + input : (typeof $TEXT == "string" + ? tokenizer($TEXT, options.filename, + options.html5_comments) + : $TEXT), + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + function handle_regexp() { + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + }; + + var statement = embed_tokens(function() { + var tmp; + handle_regexp(); + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(AST_Defun); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + if (!(stat instanceof AST_IterationStatement)) { + // check for `continue` that refers to this label. + // those should be reported as syntax errors. + // https://github.com/mishoo/UglifyJS2/issues/287 + label.references.forEach(function(ref){ + if (ref instanceof AST_Continue) { + ref = ref.label.start; + croak("Continue label `" + label.name + "` refers to non-IterationStatement.", + ref.line, ref.col, ref.pos); + } + }); + } + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null, ldef; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + ldef = find_if(function(l){ return l.name == label.name }, S.labels); + if (!ldef) + croak("Undefined label " + label.name); + label.thedef = ldef; + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + var stat = new type({ label: label }); + if (ldef) ldef.references.push(stat); + return stat; + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(ctor) { + var in_statement = ctor === AST_Defun; + var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; + if (in_statement && !name) + unexpected(); + expect("("); + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + case "keyword": + ret = _make_symbol(AST_SymbolRef); + break; + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(AST_Function); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : as_atom_node(), + value : function_(AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : as_atom_node(), + value : function_(AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function _make_symbol(type) { + var name = S.token.value; + return new (name == "this" ? AST_This : type)({ + name : String(name), + start : S.token, + end : S.token + }); + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var sym = _make_symbol(type); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + handle_regexp(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + if (expr instanceof AST_This) return false; + return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol); + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + if (options.expression) { + return expression(true); + } + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js new file mode 100644 index 000000000..49b04811b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,556 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return (this.global && !(options && options.toplevel)) + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda) + s = s.parent_scope; + this.mangled_name = s.next_mangled(options, this); + } + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + ++nesting; + scope = node; + descend(); + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + g.global = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (func && name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = ext.length; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Function.DEFMETHOD("next_mangled", function(options, def){ + // #179, #326 + // in Safari strict mode, something like (function x(x){...}) is a syntax error; + // a function expression's argument cannot shadow the function expression's name + + var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition(); + while (true) { + var name = AST_Lambda.prototype.next_mangled.call(this, options, def); + if (!(tricky_def && tricky_def.mangled_name == name)) + return name; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/sourcemap.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 000000000..342990812 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/transform.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/transform.js new file mode 100644 index 000000000..c3c34f589 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,218 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + self.name = self.name.transform(tw); + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/utils.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/utils.js new file mode 100644 index 000000000..73964a09b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,295 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function all(array, predicate) { + for (var i = array.length; --i >= 0;) + if (!predicate(array[i])) + return false; + return true; +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/LICENSE new file mode 100644 index 000000000..b7f9d5001 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/README.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/README.md new file mode 100644 index 000000000..9ff1acfdf --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/README.md @@ -0,0 +1,1414 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. Also supports [component](https://github.com/component/component). + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about bind, not about async. If you are wondering how to +make async execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [forever](#forever) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then it's probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, callback) + +Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. +If an error is passed to fn's callback then 'callback' is called with the +error, otherwise it will never be called. + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as applyEach only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing an array of + queued tasks, which must call its callback(err) argument when finished, with + an optional error as an argument. +* payload - An optional integer for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8'); +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. It's also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/component.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/component.json new file mode 100644 index 000000000..bbb011548 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/component.json @@ -0,0 +1,11 @@ +{ + "name": "async", + "repo": "caolan/async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.1.23", + "keywords": [], + "dependencies": {}, + "development": {}, + "main": "lib/async.js", + "scripts": [ "lib/async.js" ] +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/lib/async.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/lib/async.js new file mode 100755 index 000000000..cb6320d6a --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/async/lib/async.js @@ -0,0 +1,955 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = setImmediate; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n queued tasks, which must call its callback(err) argument when finished, with \n an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8');\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", + "_id": "async@0.2.9", + "dist": { + "shasum": "93885d93f14550270027c9fd4ee106d88eb20b66" + }, + "_from": "async@~0.2.6", + "_resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/.travis.yml b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/.travis.yml new file mode 100644 index 000000000..cc4dba29d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/LICENSE new file mode 100644 index 000000000..432d1aeb0 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/bool.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/bool.js new file mode 100644 index 000000000..a998fb7ab --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/bool.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js new file mode 100644 index 000000000..a35a7e6d3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js new file mode 100644 index 000000000..017bb6893 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_hash.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_hash.js new file mode 100644 index 000000000..ade77681d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_hash.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; + +console.log(argv.x + argv.y); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_singles.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_singles.js new file mode 100644 index 000000000..d9b1ff458 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/default_singles.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/divide.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/divide.js new file mode 100644 index 000000000..5e2ee82ff --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/divide.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count.js new file mode 100644 index 000000000..b5f95bf6d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js new file mode 100644 index 000000000..d9ac70904 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .options({ + file : { + demand : true, + alias : 'f', + description : 'Load a file' + }, + base : { + alias : 'b', + description : 'Numeric base to use for output', + default : 10, + }, + }) + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js new file mode 100644 index 000000000..426751112 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .wrap(80) + .demand('f') + .alias('f', [ 'file', 'filename' ]) + .describe('f', + "Load a file. It's pretty important." + + " Required even. So you'd better specify it." + ) + .alias('b', 'base') + .describe('b', 'Numeric base to display the number of lines in') + .default('b', 10) + .describe('x', 'Super-secret optional parameter which is secret') + .default('x', '') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/nonopt.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/nonopt.js new file mode 100644 index 000000000..ee633eedc --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/nonopt.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/reflect.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/reflect.js new file mode 100644 index 000000000..816b3e111 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/reflect.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.dir(require('optimist').argv); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/short.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/short.js new file mode 100644 index 000000000..1db0ad0f8 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/short.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/string.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/string.js new file mode 100644 index 000000000..a8e5aeb23 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/string.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +var argv = require('optimist') + .string('x', 'y') + .argv +; +console.dir([ argv.x, argv.y ]); + +/* Turns off numeric coercion: + ./node string.js -x 000123 -y 9876 + [ '000123', '9876' ] +*/ diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/usage-options.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/usage-options.js new file mode 100644 index 000000000..b99997767 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/usage-options.js @@ -0,0 +1,19 @@ +var optimist = require('./../index'); + +var argv = optimist.usage('This is my awesome program', { + 'about': { + description: 'Provide some details about the author of this program', + required: true, + short: 'a', + }, + 'info': { + description: 'Provide some information about the node.js agains!!!!!!', + boolean: true, + short: 'i' + } +}).argv; + +optimist.showHelp(); + +console.log('\n\nInspecting options'); +console.dir(argv); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/xup.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/xup.js new file mode 100644 index 000000000..8f6ecd201 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/example/xup.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} + diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/index.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/index.js new file mode 100644 index 000000000..8ac67eb31 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/index.js @@ -0,0 +1,478 @@ +var path = require('path'); +var wordwrap = require('wordwrap'); + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('optimist')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('optimist').argv + to get a parsed version of process.argv. +*/ + +var inst = Argv(process.argv.slice(2)); +Object.keys(inst).forEach(function (key) { + Argv[key] = typeof inst[key] == 'function' + ? inst[key].bind(inst) + : inst[key]; +}); + +var exports = module.exports = Argv; +function Argv (args, cwd) { + var self = {}; + if (!cwd) cwd = process.cwd(); + + self.$0 = process.argv + .slice(0,2) + .map(function (x) { + var b = rebase(cwd, x); + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ') + ; + + if (process.env._ != undefined && process.argv[1] == process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ); + } + + var flags = { bools : {}, strings : {} }; + + self.boolean = function (bools) { + if (!Array.isArray(bools)) { + bools = [].slice.call(arguments); + } + + bools.forEach(function (name) { + flags.bools[name] = true; + }); + + return self; + }; + + self.string = function (strings) { + if (!Array.isArray(strings)) { + strings = [].slice.call(arguments); + } + + strings.forEach(function (name) { + flags.strings[name] = true; + }); + + return self; + }; + + var aliases = {}; + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]); + }); + } + else if (Array.isArray(y)) { + y.forEach(function (yy) { + self.alias(x, yy); + }); + } + else { + var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); + aliases[x] = zs.filter(function (z) { return z != x }); + aliases[y] = zs.filter(function (z) { return z != y }); + } + + return self; + }; + + var demanded = {}; + self.demand = function (keys) { + if (typeof keys == 'number') { + if (!demanded._) demanded._ = 0; + demanded._ += keys; + } + else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key); + }); + } + else { + demanded[keys] = true; + } + + return self; + }; + + var usage; + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg; + msg = null; + } + + usage = msg; + + if (opts) self.options(opts); + + return self; + }; + + function fail (msg) { + self.showHelp(); + if (msg) console.error(msg); + process.exit(1); + } + + var checks = []; + self.check = function (f) { + checks.push(f); + return self; + }; + + var defaults = {}; + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + defaults[key] = value; + } + + return self; + }; + + var descriptions = {}; + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]); + }); + } + else { + descriptions[key] = desc; + } + return self; + }; + + self.parse = function (args) { + return Argv(args).argv; + }; + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]); + }); + } + else { + if (opt.alias) self.alias(key, opt.alias); + if (opt.demand) self.demand(key); + if (typeof opt.default !== 'undefined') { + self.default(key, opt.default); + } + + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + } + if (opt.string || opt.type === 'string') { + self.string(key); + } + + var desc = opt.describe || opt.description || opt.desc; + if (desc) { + self.describe(key, desc); + } + } + + return self; + }; + + var wrap = null; + self.wrap = function (cols) { + wrap = cols; + return self; + }; + + self.showHelp = function (fn) { + if (!fn) fn = console.error; + fn(self.help()); + }; + + self.help = function () { + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(defaults)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true; + return acc; + }, {}) + ); + + var help = keys.length ? [ 'Options:' ] : []; + + if (usage) { + help.unshift(usage.replace(/\$0/g, self.$0), ''); + } + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(aliases[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + ; + return acc; + }, {}); + + var switchlen = longest(Object.keys(switches).map(function (s) { + return switches[s] || ''; + })); + + var desclen = longest(Object.keys(descriptions).map(function (d) { + return descriptions[d] || ''; + })); + + keys.forEach(function (key) { + var kswitch = switches[key]; + var desc = descriptions[key] || ''; + + if (wrap) { + desc = wordwrap(switchlen + 4, wrap)(desc) + .slice(switchlen + 4) + ; + } + + var spadding = new Array( + Math.max(switchlen - kswitch.length + 3, 0) + ).join(' '); + + var dpadding = new Array( + Math.max(desclen - desc.length + 1, 0) + ).join(' '); + + var type = null; + + if (flags.bools[key]) type = '[boolean]'; + if (flags.strings[key]) type = '[string]'; + + if (!wrap && dpadding.length > 0) { + desc += dpadding; + } + + var prelude = ' ' + kswitch + spadding; + var extra = [ + type, + demanded[key] + ? '[required]' + : null + , + defaults[key] !== undefined + ? '[default: ' + JSON.stringify(defaults[key]) + ']' + : null + , + ].filter(Boolean).join(' '); + + var body = [ desc, extra ].filter(Boolean).join(' '); + + if (wrap) { + var dlines = desc.split('\n'); + var dlen = dlines.slice(-1)[0].length + + (dlines.length === 1 ? prelude.length : 0) + + body = desc + (dlen + extra.length > wrap - 2 + ? '\n' + + new Array(wrap - extra.length + 1).join(' ') + + extra + : new Array(wrap - extra.length - dlen + 1).join(' ') + + extra + ); + } + + help.push(prelude + body); + }); + + help.push(''); + return help.join('\n'); + }; + + Object.defineProperty(self, 'argv', { + get : parseArgs, + enumerable : true, + }); + + function parseArgs () { + var argv = { _ : [], $0 : self.$0 }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] || false); + }); + + function setArg (key, val) { + var num = Number(val); + var value = typeof val !== 'string' || isNaN(num) ? val : num; + if (flags.strings[key]) value = val; + + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + argv[x] = argv[key]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (arg === '--') { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + else if (arg.match(/^--.+=/)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + setArg(m[1], m[2]); + } + else if (arg.match(/^--no-.+/)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (arg.match(/^--.+/)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !next.match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, next); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, true); + } + } + else if (arg.match(/^-[^-]+/)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], true); + } + } + + if (!broken) { + var key = arg.slice(-1)[0]; + + if (args[i+1] && !args[i+1].match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, true); + } + } + } + else { + var n = Number(arg); + argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!(key in argv)) { + argv[key] = defaults[key]; + if (key in aliases) { + argv[aliases[key]] = defaults[key]; + } + } + }); + + if (demanded._ && argv._.length < demanded._) { + fail('Not enough non-option arguments: got ' + + argv._.length + ', need at least ' + demanded._ + ); + } + + var missing = []; + Object.keys(demanded).forEach(function (key) { + if (!argv[key]) missing.push(key); + }); + + if (missing.length) { + fail('Missing required arguments: ' + missing.join(', ')); + } + + checks.forEach(function (f) { + try { + if (f(argv) === false) { + fail('Argument check failed: ' + f.toString()); + } + } + catch (err) { + fail(err) + } + }); + + return argv; + } + + function longest (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length }) + ); + } + + return self; +}; + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase; +function rebase (base, dir) { + var ds = path.normalize(dir).split('/').slice(1); + var bs = path.normalize(base).split('/').slice(1); + + for (var i = 0; ds[i] && ds[i] == bs[i]; i++); + ds.splice(0, i); bs.splice(0, i); + + var p = path.normalize( + bs.map(function () { return '..' }).concat(ds).join('/') + ).replace(/\/$/,'').replace(/^$/, '.'); + return p.match(/^[.\/]/) ? p : './' + p; +}; + +function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown new file mode 100644 index 000000000..346374e0d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js new file mode 100644 index 000000000..a3fbaae98 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js new file mode 100644 index 000000000..a4665e105 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js new file mode 100644 index 000000000..c9bc94521 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json new file mode 100644 index 000000000..054825b82 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json @@ -0,0 +1,48 @@ +{ + "name": "wordwrap", + "description": "Wrap those words. Show them at what columns to start and stop.", + "version": "0.0.2", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "main": "./index.js", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "expresso" + }, + "devDependencies": { + "expresso": "=0.7.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT/X11", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n var wrap = require('wordwrap')(15);\n console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n You and your\n whole family\n are made out\n of meat.\n\ncentered\n--------\n\ncenter.js\n\n var wrap = require('wordwrap')(20, 60);\n console.log(wrap(\n 'At long last the struggle and tumult was over.'\n + ' The machines had finally cast off their oppressors'\n + ' and were finally free to roam the cosmos.'\n + '\\n'\n + 'Free of purpose, free of obligation.'\n + ' Just drifting through emptiness.'\n + ' The sun was just another point of light.'\n ));\n\noutput:\n\n At long last the struggle and tumult\n was over. The machines had finally cast\n off their oppressors and were finally\n free to roam the cosmos.\n Free of purpose, free of obligation.\n Just drifting through emptiness. The\n sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n", + "readmeFilename": "README.markdown", + "bugs": { + "url": "https://github.com/substack/node-wordwrap/issues" + }, + "_id": "wordwrap@0.0.2", + "dist": { + "shasum": "0afbf84933a84270f8a701f23fd2d8e0cdccec65" + }, + "_from": "wordwrap@~0.0.2", + "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js new file mode 100644 index 000000000..749292ecc --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 000000000..aa3f4907f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js new file mode 100644 index 000000000..0cfb76d17 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/package.json new file mode 100644 index 000000000..329d8006f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/package.json @@ -0,0 +1,49 @@ +{ + "name": "optimist", + "version": "0.3.7", + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "main": "./index.js", + "dependencies": { + "wordwrap": "~0.0.2" + }, + "devDependencies": { + "hashish": "~0.0.4", + "tap": "~0.4.0" + }, + "scripts": { + "test": "tap ./test/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-optimist.git" + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "node": ">=0.4" + }, + "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "readmeFilename": "readme.markdown", + "bugs": { + "url": "https://github.com/substack/node-optimist/issues" + }, + "_id": "optimist@0.3.7", + "dist": { + "shasum": "995700f900820c2ed042ffdb4ba72060e869bcef" + }, + "_from": "optimist@~0.3.5", + "_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/readme.markdown b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/readme.markdown new file mode 100644 index 000000000..ad9d3fd68 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/readme.markdown @@ -0,0 +1,487 @@ +optimist +======== + +Optimist is a node.js library for option parsing for people who hate option +parsing. More specifically, this module is for people who like all the --bells +and -whistlz of program usage but think optstrings are a waste of time. + +With optimist, option parsing doesn't have to suck (as much). + +[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist) + +examples +======== + +With Optimist, the options are just a hash! No optstrings attached. +------------------------------------------------------------------- + +xup.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} +```` + +*** + + $ ./xup.js --rif=55 --xup=9.52 + Buy more riffiwobbles + + $ ./xup.js --rif 12 --xup 8.1 + Sell the xupptumblers + +![This one's optimistic.](http://substack.net/images/optimistic.png) + +But wait! There's more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long and short (and grouped): +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); +```` + +*** + + $ ./bool.js -s + The cat says: meow + + $ ./bool.js -sp + The cat says: meow. + + $ ./bool.js -sp --fr + Le chat dit: miaou. + +And non-hypenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 moo + (6.82,3.35) + [ 'moo' ] + + $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz + (0.54,1.12) + [ 'foo', 'bar', 'baz' ] + +Plus, Optimist comes with .usage() and .demand()! +------------------------------------------------- + +divide.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); +```` + +*** + + $ ./divide.js -x 55 -y 11 + 5 + + $ node ./divide.js -x 4.91 -z 2.51 + Usage: node ./divide.js -x [num] -y [num] + + Options: + -x [required] + -y [required] + + Missing required arguments: y + +EVEN MORE HOLY COW +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv); +```` + +*** + + $ ./boolean_single.js -v foo bar baz + true + [ 'bar', 'baz', 'foo' ] + +boolean_double.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Optimist is here to help... +--------------------------- + +You can describe parameters for help messages and set aliases. Optimist figures +out how to format a handy help string automatically. + +line_count.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + + $ node line_count.js + Count the lines in a file. + Usage: node ./line_count.js + + Options: + -f, --file Load a file [required] + + Missing required arguments: f + + $ node line_count.js --file line_count.js + 20 + + $ node line_count.js -f line_count.js + 20 + +methods +======= + +By itself, + +````javascript +require('optimist').argv +````` + +will use `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('optimist')([ '-x', '1', '-y', '2' ]).argv +```` + +or use .parse() to do the same thing: + +````javascript +require('optimist').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. + +.default(key, value) +-------------------- + +Set `argv[key]` to `value` if no option was specified on `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +.demand(key) +------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. + +If `key` is an Array, demand each element. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('optimist') + .options('f', { + alias : 'file', + default : '/etc/passwd', + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('optimist') + .alias('f', 'file') + .default('f', '/etc/passwd') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +.usage(message) +--------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +If `fn` throws or returns `false`, show the thrown error, usage information, and +exit. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be +`false`. + +If `key` is an Array, interpret all the elements as booleans. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an Array, interpret all the elements as strings. + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +.help() +------- + +Return the generated usage string. + +.showHelp(fn=console.error) +--------------------------- + +Print the usage data using `fn` for printing. + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + '$0': 'node ./examples/reflect.js', + a: 1, + b: 2 } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], + '$0': 'node ./examples/reflect.js', + a: true, + b: false } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], + '$0': 'node ./examples/reflect.js', + x: [ 5, 8, 0 ] } + +dot notation +------------ + +When you use dots (`.`s) in argument names, an implicit object path is assumed. +This lets you organize arguments into nested objects. + + $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 + { _: [], + '$0': 'node ./examples/reflect.js', + foo: { bar: { baz: 33 }, quux: 5 } } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install optimist + +or clone this project on github: + + git clone http://github.com/substack/node-optimist.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + +inspired By +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_.js new file mode 100644 index 000000000..d9c58b368 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_.js @@ -0,0 +1,71 @@ +var spawn = require('child_process').spawn; +var test = require('tap').test; + +test('dotSlashEmpty', testCmd('./bin.js', [])); + +test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ])); + +test('nodeEmpty', testCmd('node bin.js', [])); + +test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ])); + +test('whichNodeEmpty', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', []) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + assert.error(err); + t.end(); + }); +}); + +test('whichNodeArgs', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); +}); + +function testCmd (cmd, args) { + + return function (t) { + var to = setTimeout(function () { + assert.fail('Never got stdout data.') + }, 5000); + + var oldDir = process.cwd(); + process.chdir(__dirname + '/_'); + + var cmds = cmd.split(' '); + + var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); + process.chdir(oldDir); + + bin.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); + + bin.stdout.on('data', function (buf) { + clearTimeout(to); + var _ = JSON.parse(buf.toString()); + t.same(_.map(String), args.map(String)); + t.end(); + }); + }; +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/argv.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/argv.js new file mode 100644 index 000000000..3d096062c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/argv.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log(JSON.stringify(process.argv)); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/bin.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/bin.js new file mode 100755 index 000000000..4a18d85f3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/_/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('../../index').argv +console.log(JSON.stringify(argv._)); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/parse.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/parse.js new file mode 100644 index 000000000..d320f4336 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/parse.js @@ -0,0 +1,446 @@ +var optimist = require('../index'); +var path = require('path'); +var test = require('tap').test; + +var $0 = 'node ./' + path.relative(process.cwd(), __filename); + +test('short boolean', function (t) { + var parse = optimist.parse([ '-b' ]); + t.same(parse, { b : true, _ : [], $0 : $0 }); + t.same(typeof parse.b, 'boolean'); + t.end(); +}); + +test('long boolean', function (t) { + t.same( + optimist.parse([ '--bool' ]), + { bool : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('bare', function (t) { + t.same( + optimist.parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 } + ); + t.end(); +}); + +test('short group', function (t) { + t.same( + optimist.parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short group next', function (t) { + t.same( + optimist.parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short captures', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture sp', function (t) { + t.same( + optimist.parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture eq', function (t) { + t.same( + optimist.parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end() +}); + +test('long captures sp', function (t) { + t.same( + optimist.parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long captures eq', function (t) { + t.same( + optimist.parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('no', function (t) { + t.same( + optimist.parse([ '--no-moo' ]), + { moo : false, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('multi', function (t) { + t.same( + optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [], $0 : $0 } + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.same( + optimist.parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ], + $0 : $0 + } + ); + t.end(); +}); + +test('nums', function (t) { + var argv = optimist.parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.same(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ], + $0 : $0 + }); + t.same(typeof argv.x, 'number'); + t.same(typeof argv.y, 'number'); + t.same(typeof argv.z, 'number'); + t.same(typeof argv.w, 'string'); + t.same(typeof argv.hex, 'number'); + t.same(typeof argv._[0], 'number'); + t.end(); +}); + +test('flag boolean', function (t) { + var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; + t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 }); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) + .boolean(['t', 'verbose']).default('verbose', true).argv; + + t.same(parse, { + verbose: false, + t: true, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean default false', function (t) { + var parse = optimist(['moo']) + .boolean(['t', 'verbose']) + .default('verbose', false) + .default('t', false).argv; + + t.same(parse, { + verbose: false, + t: false, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) + .boolean(['x','y','z']).argv; + + t.same(parse, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ], + $0 : $0 + }); + + t.same(typeof parse.x, 'boolean'); + t.same(typeof parse.y, 'boolean'); + t.same(typeof parse.z, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = optimist.parse([ '-s', "X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = optimist.parse([ "--s=X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + t.end(); +}); + +test('strings' , function (t) { + var s = optimist([ '-s', '0001234' ]).string('s').argv.s; + t.same(s, '0001234'); + t.same(typeof s, 'string'); + + var x = optimist([ '-x', '56' ]).string('x').argv.x; + t.same(x, '56'); + t.same(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = optimist([ ' ', ' ' ]).string('_').argv._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + optimist.parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.same( + optimist.parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', 'zoom') + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', [ 'zm', 'zoom' ]) + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('boolean default true', function (t) { + var argv = optimist.options({ + sometrue: { + boolean: true, + default: true + } + }).argv; + + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = optimist.options({ + somefalse: { + boolean: true, + default: false + } + }).argv; + + t.equal(argv.somefalse, false); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = optimist([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]).argv; + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + }, + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); + +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('herp') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('herp') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .options(opts) + .argv; + var propertyArgv = optimist(regular).options(opts).argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('h') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('h') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = optimist(['--boool', '--other=false']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/usage.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/usage.js new file mode 100644 index 000000000..300454c1e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/optimist/test/usage.js @@ -0,0 +1,292 @@ +var Hash = require('hashish'); +var optimist = require('../index'); +var test = require('tap').test; + +test('usageFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'Options:', + ' -x [required]', + ' -y [required]', + 'Missing required arguments: y', + ] + ); + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + + +test('usagePass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkPass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'You forgot about -y' + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('checkCondPass', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkCondFail', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/).join('\n'), + 'Usage: ./usage -x NUM -y NUM\n' + + 'Argument check failed: ' + checker.toString() + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('countPass', function (t) { + var r = checkUsage(function () { + return optimist('1 2 3 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same(r, { + result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('countFail', function (t) { + var r = checkUsage(function () { + return optimist('1 2 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same( + r.result, + { _ : [ '1', '2' ], moo : true, $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage [x] [y] [z] {OPTIONS}', + 'Not enough non-option arguments: got 2, need at least 3', + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('defaultSingles', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70 --powsy'.split(' ')) + .default('foo', 5) + .default('bar', 6) + .default('baz', 7) + .argv + ; + }); + t.same(r.result, { + foo : '50', + bar : 6, + baz : '70', + powsy : true, + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultAliases', function (t) { + var r = checkUsage(function () { + return optimist('') + .alias('f', 'foo') + .default('f', 5) + .argv + ; + }); + t.same(r.result, { + f : '5', + foo : '5', + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultHash', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70'.split(' ')) + .default({ foo : 10, bar : 20, quux : 30 }) + .argv + ; + }); + t.same(r.result, { + _ : [], + $0 : './usage', + foo : 50, + baz : 70, + bar : 20, + quux : 30, + }); + t.end(); +}); + +test('rebase', function (t) { + t.equal( + optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), + './foo/bar/baz' + ); + t.equal( + optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), + '../../..' + ); + t.equal( + optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), + '../pow/zoom.txt' + ); + t.end(); +}); + +function checkUsage (f) { + + var exit = false; + + process._exit = process.exit; + process._env = process.env; + process._argv = process.argv; + + process.exit = function (t) { exit = true }; + process.env = Hash.merge(process.env, { _ : 'node' }); + process.argv = [ './usage' ]; + + var errors = []; + var logs = []; + + console._error = console.error; + console.error = function (msg) { errors.push(msg) }; + console._log = console.log; + console.log = function (msg) { logs.push(msg) }; + + var result = f(); + + process.exit = process._exit; + process.env = process._env; + process.argv = process._argv; + + console.error = console._error; + console.log = console._log; + + return { + errors : errors, + logs : logs, + exit : exit, + result : result, + }; +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.npmignore new file mode 100644 index 000000000..3dddf3f67 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.travis.yml b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.travis.yml new file mode 100644 index 000000000..ddc9c4f98 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md new file mode 100644 index 000000000..98b90d52b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,112 @@ +# Change Log + +## 0.1.31 + +* Delay parsing the mappings in SourceMapConsumer until queried for a source + location. + +* Support Sass source maps (which at the time of writing deviate from the spec + in small ways) in SourceMapConsumer. + +## 0.1.30 + +* Do not join source root with a source, when the source is a data URI. + +* Extend the test runner to allow running single specific test files at a time. + +* Performance improvements in `SourceNode.prototype.walk` and + `SourceMapConsumer.prototype.eachMapping`. + +* Source map browser builds will now work inside Workers. + +* Better error messages when attempting to add an invalid mapping to a + `SourceMapGenerator`. + +## 0.1.29 + +* Allow duplicate entries in the `names` and `sources` arrays of source maps + (usually from TypeScript) we are parsing. Fixes github isse 72. + +## 0.1.28 + +* Skip duplicate mappings when creating source maps from SourceNode; github + issue 75. + +## 0.1.27 + +* Don't throw an error when the `file` property is missing in SourceMapConsumer, + we don't use it anyway. + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. + diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/LICENSE new file mode 100644 index 000000000..ed1b7cf27 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 000000000..d6fc26a79 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/README.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/README.md new file mode 100644 index 000000000..c20437bc6 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/README.md @@ -0,0 +1,434 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +This library is written in the Asynchronous Module Definition format, and works +in the following environments: + +* Modern Browsers supporting ECMAScript 5 (either after the build, or with an + AMD loader such as RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Node + + $ npm install source-map + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should spew a bunch of stuff to stdout, and create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. + +## Examples + +### Consuming a source map + + var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + + var smc = new SourceMapConsumer(rawSourceMap); + + console.log(smc.sources); + // [ 'http://example.com/www/js/one.js', + // 'http://example.com/www/js/two.js' ] + + console.log(smc.originalPositionFor({ + line: 2, + column: 28 + })); + // { source: 'http://example.com/www/js/two.js', + // line: 2, + // column: 10, + // name: 'n' } + + console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 + })); + // { line: 2, column: 28 } + + smc.eachMapping(function (m) { + // ... + }); + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + + function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } + } + + var ast = parse("40 + 2", "add.js"); + console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' + })); + // { code: '40 + 2', + // map: [object SourceMapGenerator] } + +#### With SourceMapGenerator (low level API) + + var map = new SourceMapGenerator({ + file: "source-mapped.js" + }); + + map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" + }); + + console.log(map.toString()); + // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator(startOfSourceMap) + +To create a new one, you must pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: An optional root for all relative URLs in this source map. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used. + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode(line, column, source[, chunk[, name]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js new file mode 100644 index 000000000..daa1a623c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/mini-require.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/mini-require.js new file mode 100644 index 000000000..0daf45377 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 000000000..ee2539d81 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 000000000..80341d452 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 000000000..fb29ff5fd --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 000000000..cf3c2d8d3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 000000000..b31b84cb6 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js new file mode 100644 index 000000000..1b13f300e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js new file mode 100644 index 000000000..bec2de3f2 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map.js new file mode 100644 index 000000000..121ad2416 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 000000000..40f9a18b1 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,97 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 000000000..1b67bb375 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,144 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 000000000..863cc4650 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 000000000..ff347c68b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,81 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 000000000..a3b9dc086 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,477 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.slice() + .sort(util.compareByGeneratedPositions); + smc.__originalMappings = aSourceMap._mappings.slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 000000000..48ead7ddc --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,380 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.originalLine) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + orginal: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(util.compareByGeneratedPositions); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 000000000..626cb6574 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,371 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i] instanceof SourceNode) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 000000000..87946d3f7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,205 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + var dataUrlRegexp = /^data:.+\,.+/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE new file mode 100644 index 000000000..f33d665de --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * 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. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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. + + + +MIT License +----------- + +Copyright (c) 2011, The Dojo Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md new file mode 100644 index 000000000..c6995c072 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md @@ -0,0 +1,171 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.1.0" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +### amdefine/intercept + +Consider this very experimental. + +Instead of pasting the piece of text for the amdefine setup of a `define` +variable in each module you create or consume, you can use `amdefine/intercept` +instead. It will automatically insert the above snippet in each .js file loaded +by Node. + +**Warning**: you should only use this if you are creating an application that +is consuming AMD style defined()'d modules that are distributed via npm and want +to run that code in Node. + +For library code where you are not sure if it will be used by others in Node or +in the browser, then explicitly depending on amdefine and placing the code +snippet above is suggested path, instead of using `amdefine/intercept`. The +intercept module affects all .js files loaded in the Node app, and it is +inconsiderate to modify global state like that unless you are also controlling +the top level app. + +#### Why distribute AMD-style nodes via npm? + +npm has a lot of weaknesses for front-end use (installed layout is not great, +should have better support for the `baseUrl + moduleID + '.js' style of loading, +single file JS installs), but some people want a JS package manager and are +willing to live with those constraints. If that is you, but still want to author +in AMD style modules to get dynamic require([]), better direct source usage and +powerful loader plugin support in the browser, then this tool can help. + +#### amdefine/intercept usage + +Just require it in your top level app module (for example index.js, server.js): + +```javascript +require('amdefine/intercept'); +``` + +The module does not return a value, so no need to assign the result to a local +variable. + +Then just require() code as you normally would with Node's require(). Any .js +loaded after the intercept require will have the amdefine check injected in +the .js source as it is loaded. It does not modify the source on disk, just +prepends some content to the text of the module as it is loaded by Node. + +#### How amdefine/intercept works + +It overrides the `Module._extensions['.js']` in Node to automatically prepend +the amdefine snippet above. So, it will affect any .js file loaded by your +app. + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +node all-intercept.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js new file mode 100644 index 000000000..53bf5a686 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js @@ -0,0 +1,299 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js new file mode 100644 index 000000000..771a98301 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/intercept.js @@ -0,0 +1,36 @@ +/*jshint node: true */ +var inserted, + Module = require('module'), + fs = require('fs'), + existingExtFn = Module._extensions['.js'], + amdefineRegExp = /amdefine\.js/; + +inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; + +//From the node/lib/module.js source: +function stripBOM(content) { + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +//Also adapted from the node/lib/module.js source: +function intercept(module, filename) { + var content = stripBOM(fs.readFileSync(filename, 'utf8')); + + if (!amdefineRegExp.test(module.id)) { + content = inserted + content; + } + + module._compile(content, filename); +} + +intercept._id = 'amdefine/intercept'; + +if (!existingExtFn._id || existingExtFn._id !== intercept._id) { + Module._extensions['.js'] = intercept; +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json new file mode 100644 index 000000000..fa9b08322 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json @@ -0,0 +1,40 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "0.1.0", + "homepage": "http://github.com/jrburke/amdefine", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + }, + "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.1.0\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n### amdefine/intercept\n\nConsider this very experimental.\n\nInstead of pasting the piece of text for the amdefine setup of a `define`\nvariable in each module you create or consume, you can use `amdefine/intercept`\ninstead. It will automatically insert the above snippet in each .js file loaded\nby Node.\n\n**Warning**: you should only use this if you are creating an application that\nis consuming AMD style defined()'d modules that are distributed via npm and want\nto run that code in Node.\n\nFor library code where you are not sure if it will be used by others in Node or\nin the browser, then explicitly depending on amdefine and placing the code\nsnippet above is suggested path, instead of using `amdefine/intercept`. The\nintercept module affects all .js files loaded in the Node app, and it is\ninconsiderate to modify global state like that unless you are also controlling\nthe top level app.\n\n#### Why distribute AMD-style nodes via npm?\n\nnpm has a lot of weaknesses for front-end use (installed layout is not great,\nshould have better support for the `baseUrl + moduleID + '.js' style of loading,\nsingle file JS installs), but some people want a JS package manager and are\nwilling to live with those constraints. If that is you, but still want to author\nin AMD style modules to get dynamic require([]), better direct source usage and\npowerful loader plugin support in the browser, then this tool can help.\n\n#### amdefine/intercept usage\n\nJust require it in your top level app module (for example index.js, server.js):\n\n```javascript\nrequire('amdefine/intercept');\n```\n\nThe module does not return a value, so no need to assign the result to a local\nvariable.\n\nThen just require() code as you normally would with Node's require(). Any .js\nloaded after the intercept require will have the amdefine check injected in\nthe .js source as it is loaded. It does not modify the source on disk, just\nprepends some content to the text of the module as it is loaded by Node.\n\n#### How amdefine/intercept works\n\nIt overrides the `Module._extensions['.js']` in Node to automatically prepend\nthe amdefine snippet above. So, it will affect any .js file loaded by your\napp.\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\nnode all-intercept.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/jrburke/amdefine/issues" + }, + "_id": "amdefine@0.1.0", + "dist": { + "shasum": "83bf9967572ac1003f7dd965b10694ba6c624218" + }, + "_from": "amdefine@>=0.0.4", + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/package.json new file mode 100644 index 000000000..2a8813d77 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/package.json @@ -0,0 +1,114 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.31", + "homepage": "https://github.com/mozilla/source-map", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + }, + { + "name": "Chase Douglas", + "email": "chase@newrelic.com" + }, + { + "name": "Evan Wallace", + "email": "evan.exe@gmail.com" + }, + { + "name": "Heather Arthur", + "email": "fayearthur@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js", + "build": "node Makefile.dryice.js" + }, + "readme": "# Source Map\n\nThis is a library to generate and consume the source map format\n[described here][format].\n\nThis library is written in the Asynchronous Module Definition format, and works\nin the following environments:\n\n* Modern Browsers supporting ECMAScript 5 (either after the build, or with an\n AMD loader such as RequireJS)\n\n* Inside Firefox (as a JSM file, after the build)\n\n* With NodeJS versions 0.8.X and higher\n\n## Node\n\n $ npm install source-map\n\n## Building from Source (for everywhere else)\n\nInstall Node and then run\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\nNext, run\n\n $ node Makefile.dryice.js\n\nThis should spew a bunch of stuff to stdout, and create the following files:\n\n* `dist/source-map.js` - The unminified browser version.\n\n* `dist/source-map.min.js` - The minified browser version.\n\n* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source.\n\n## Examples\n\n### Consuming a source map\n\n var rawSourceMap = {\n version: 3,\n file: 'min.js',\n names: ['bar', 'baz', 'n'],\n sources: ['one.js', 'two.js'],\n sourceRoot: 'http://example.com/www/js/',\n mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'\n };\n\n var smc = new SourceMapConsumer(rawSourceMap);\n\n console.log(smc.sources);\n // [ 'http://example.com/www/js/one.js',\n // 'http://example.com/www/js/two.js' ]\n\n console.log(smc.originalPositionFor({\n line: 2,\n column: 28\n }));\n // { source: 'http://example.com/www/js/two.js',\n // line: 2,\n // column: 10,\n // name: 'n' }\n\n console.log(smc.generatedPositionFor({\n source: 'http://example.com/www/js/two.js',\n line: 2,\n column: 10\n }));\n // { line: 2, column: 28 }\n\n smc.eachMapping(function (m) {\n // ...\n });\n\n### Generating a source map\n\nIn depth guide:\n[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/)\n\n#### With SourceNode (high level API)\n\n function compile(ast) {\n switch (ast.type) {\n case 'BinaryExpression':\n return new SourceNode(\n ast.location.line,\n ast.location.column,\n ast.location.source,\n [compile(ast.left), \" + \", compile(ast.right)]\n );\n case 'Literal':\n return new SourceNode(\n ast.location.line,\n ast.location.column,\n ast.location.source,\n String(ast.value)\n );\n // ...\n default:\n throw new Error(\"Bad AST\");\n }\n }\n\n var ast = parse(\"40 + 2\", \"add.js\");\n console.log(compile(ast).toStringWithSourceMap({\n file: 'add.js'\n }));\n // { code: '40 + 2',\n // map: [object SourceMapGenerator] }\n\n#### With SourceMapGenerator (low level API)\n\n var map = new SourceMapGenerator({\n file: \"source-mapped.js\"\n });\n\n map.addMapping({\n generated: {\n line: 10,\n column: 35\n },\n source: \"foo.js\",\n original: {\n line: 33,\n column: 2\n },\n name: \"christopher\"\n });\n\n console.log(map.toString());\n // '{\"version\":3,\"file\":\"source-mapped.js\",\"sources\":[\"foo.js\"],\"names\":[\"christopher\"],\"mappings\":\";;;;;;;;;mCAgCEA\"}'\n\n## API\n\nGet a reference to the module:\n\n // NodeJS\n var sourceMap = require('source-map');\n\n // Browser builds\n var sourceMap = window.sourceMap;\n\n // Inside Firefox\n let sourceMap = {};\n Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);\n\n### SourceMapConsumer\n\nA SourceMapConsumer instance represents a parsed source map which we can query\nfor information about the original file positions by giving it a file position\nin the generated source.\n\n#### new SourceMapConsumer(rawSourceMap)\n\nThe only parameter is the raw source map (either as a string which can be\n`JSON.parse`'d, or an object). According to the spec, source maps have the\nfollowing attributes:\n\n* `version`: Which version of the source map spec this map is following.\n\n* `sources`: An array of URLs to the original source files.\n\n* `names`: An array of identifiers which can be referrenced by individual\n mappings.\n\n* `sourceRoot`: Optional. The URL root from which all sources are relative.\n\n* `sourcesContent`: Optional. An array of contents of the original source files.\n\n* `mappings`: A string of base64 VLQs which contain the actual mappings.\n\n* `file`: The generated filename this source map is associated with.\n\n#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)\n\nReturns the original source, line, and column information for the generated\nsource's line and column positions provided. The only argument is an object with\nthe following properties:\n\n* `line`: The line number in the generated source.\n\n* `column`: The column number in the generated source.\n\nand an object is returned with the following properties:\n\n* `source`: The original source file, or null if this information is not\n available.\n\n* `line`: The line number in the original source, or null if this information is\n not available.\n\n* `column`: The column number in the original source, or null or null if this\n information is not available.\n\n* `name`: The original identifier, or null if this information is not available.\n\n#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)\n\nReturns the generated line and column information for the original source,\nline, and column positions provided. The only argument is an object with\nthe following properties:\n\n* `source`: The filename of the original source.\n\n* `line`: The line number in the original source.\n\n* `column`: The column number in the original source.\n\nand an object is returned with the following properties:\n\n* `line`: The line number in the generated source, or null.\n\n* `column`: The column number in the generated source, or null.\n\n#### SourceMapConsumer.prototype.sourceContentFor(source)\n\nReturns the original source content for the source provided. The only\nargument is the URL of the original source file.\n\n#### SourceMapConsumer.prototype.eachMapping(callback, context, order)\n\nIterate over each mapping between an original source/line/column and a\ngenerated line/column in this source map.\n\n* `callback`: The function that is called with each mapping. Mappings have the\n form `{ source, generatedLine, generatedColumn, originalLine, originalColumn,\n name }`\n\n* `context`: Optional. If specified, this object will be the value of `this`\n every time that `callback` is called.\n\n* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or\n `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over\n the mappings sorted by the generated file's line/column order or the\n original's source/line/column order, respectively. Defaults to\n `SourceMapConsumer.GENERATED_ORDER`.\n\n### SourceMapGenerator\n\nAn instance of the SourceMapGenerator represents a source map which is being\nbuilt incrementally.\n\n#### new SourceMapGenerator(startOfSourceMap)\n\nTo create a new one, you must pass an object with the following properties:\n\n* `file`: The filename of the generated source that this source map is\n associated with.\n\n* `sourceRoot`: An optional root for all relative URLs in this source map.\n\n#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)\n\nCreates a new SourceMapGenerator based on a SourceMapConsumer\n\n* `sourceMapConsumer` The SourceMap.\n\n#### SourceMapGenerator.prototype.addMapping(mapping)\n\nAdd a single mapping from original source line and column to the generated\nsource's line and column for this source map being created. The mapping object\nshould have the following properties:\n\n* `generated`: An object with the generated line and column positions.\n\n* `original`: An object with the original line and column positions.\n\n* `source`: The original source file (relative to the sourceRoot).\n\n* `name`: An optional original token name for this mapping.\n\n#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for an original source file.\n\n* `sourceFile` the URL of the original source file.\n\n* `sourceContent` the content of the source file.\n\n#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile])\n\nApplies a SourceMap for a source file to the SourceMap.\nEach mapping to the supplied source file is rewritten using the\nsupplied SourceMap. Note: The resolution for the resulting mappings\nis the minimium of this map and the supplied map.\n\n* `sourceMapConsumer`: The SourceMap to be applied.\n\n* `sourceFile`: Optional. The filename of the source file.\n If omitted, sourceMapConsumer.file will be used.\n\n#### SourceMapGenerator.prototype.toString()\n\nRenders the source map being generated to a string.\n\n### SourceNode\n\nSourceNodes provide a way to abstract over interpolating and/or concatenating\nsnippets of generated JavaScript source code, while maintaining the line and\ncolumn information associated between those snippets and the original source\ncode. This is useful as the final intermediate representation a compiler might\nuse before outputting the generated JS and source map.\n\n#### new SourceNode(line, column, source[, chunk[, name]])\n\n* `line`: The original line number associated with this source node, or null if\n it isn't associated with an original line.\n\n* `column`: The original column number associated with this source node, or null\n if it isn't associated with an original column.\n\n* `source`: The original source's filename.\n\n* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see\n below.\n\n* `name`: Optional. The original identifier.\n\n#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer)\n\nCreates a SourceNode from generated code and a SourceMapConsumer.\n\n* `code`: The generated code\n\n* `sourceMapConsumer` The SourceMap for the generated code\n\n#### SourceNode.prototype.add(chunk)\n\nAdd a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.prepend(chunk)\n\nPrepend a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for a source file. This will be added to the\n`SourceMap` in the `sourcesContent` field.\n\n* `sourceFile`: The filename of the source file\n\n* `sourceContent`: The content of the source file\n\n#### SourceNode.prototype.walk(fn)\n\nWalk over the tree of JS snippets in this node and its children. The walking\nfunction is called once for each snippet of JS and is passed that snippet and\nthe its original associated source's line/column location.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.walkSourceContents(fn)\n\nWalk over the tree of SourceNodes. The walking function is called for each\nsource file content and is passed the filename and source content.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.join(sep)\n\nLike `Array.prototype.join` except for SourceNodes. Inserts the separator\nbetween each of this source node's children.\n\n* `sep`: The separator.\n\n#### SourceNode.prototype.replaceRight(pattern, replacement)\n\nCall `String.prototype.replace` on the very right-most source snippet. Useful\nfor trimming whitespace from the end of a source node, etc.\n\n* `pattern`: The pattern to replace.\n\n* `replacement`: The thing to replace the pattern with.\n\n#### SourceNode.prototype.toString()\n\nReturn the string representation of this source node. Walks over the tree and\nconcatenates all the various snippets together to one string.\n\n### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap)\n\nReturns the string representation of this tree of source nodes, plus a\nSourceMapGenerator which contains all the mappings between the generated and\noriginal sources.\n\nThe arguments are the same as those to `new SourceMapGenerator`.\n\n## Tests\n\n[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)\n\nInstall NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.\n\nTo add new tests, create a new file named `test/test-.js`\nand export your test functions with names that start with \"test\", for example\n\n exports[\"test doing the foo bar\"] = function (assert, util) {\n ...\n };\n\nThe new test will be located automatically when you run the suite.\n\nThe `util` argument is the test utility module located at `test/source-map/util`.\n\nThe `assert` argument is a cut down version of node's assert module. You have\naccess to the following assertion functions:\n\n* `doesNotThrow`\n\n* `equal`\n\n* `ok`\n\n* `strictEqual`\n\n* `throws`\n\n(The reason for the restricted set of test functions is because we need the\ntests to run inside Firefox's test suite as well and so the assert module is\nshimmed in that environment. See `build/assert-shim.js`.)\n\n[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\n[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap\n[Dryice]: https://github.com/mozilla/dryice\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/mozilla/source-map/issues" + }, + "_id": "source-map@0.1.31", + "dist": { + "shasum": "1eb3b2761d276d39c4ff5e4e4683e597d73b0701" + }, + "_from": "source-map@~0.1.7", + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/run-tests.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/run-tests.js new file mode 100755 index 000000000..626c53f70 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/run-tests.js @@ -0,0 +1,71 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var failures = []; + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + } + catch (e) { + console.log('FAILED ' + tests[i].name + ': ' + k + '!'); + console.log(e.stack); + } + } + } + } + + console.log(""); + console.log(passed + ' / ' + total + ' tests passed.'); + console.log(""); + + failures.forEach(function (f) { + }); + + return failures.length; +} + +var code; + +process.stdout.on('close', function () { + process.exit(code); +}); + +function isTestFile(f) { + var testToRun = process.argv[2]; + return testToRun + ? path.basename(testToRun) === f + : /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')) + .filter(isTestFile) + .map(toModule); + +code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); +process.exit(code); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 000000000..3801233c0 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 000000000..b5797edd5 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,104 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + + exports['test .fromArray() with duplicates'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'foo']); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set = ArraySet.fromArray(['foo', 'foo'], true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + + exports['test .add() with duplicates'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + + set.add('foo'); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set.add('foo', true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 000000000..653a874e9 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,24 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result; + for (var i = -255; i < 256; i++) { + result = base64VLQ.decode(base64VLQ.encode(i)); + assert.ok(result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 000000000..ff3a24456 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 000000000..ee306830d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), null); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 18); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 000000000..d831b9262 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,72 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + + // Fuzzy + + // Original to generated + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + + // Generated to original + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 000000000..f2c65a7f0 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,451 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an objects'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var sources = map.sources; + + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var mapping; + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + + exports['test github issue #72, duplicate sources'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source1.js", "source1.js", "source3.js"], + "names": [], + "mappings": ";EAAC;;IAEE;;MEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.source, 'http://example.com/source3.js'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test github issue #72, duplicate names'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source.js"], + "names": ["name1", "name1", "name3"], + "mappings": ";EAACA;;IAEEA;;MAEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.name, 'name3'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { + var smg = new SourceMapGenerator({ + sourceRoot: 'http://example.com/', + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 4, column: 4 }, + source: 'baz.js', + name: 'dirtMcGirt' + }); + smg.setSourceContent('baz.js', 'baz.js content'); + + var smc = SourceMapConsumer.fromSourceMap(smg); + assert.equal(smc.file, 'foo.js'); + assert.equal(smc.sourceRoot, 'http://example.com/'); + assert.equal(smc.sources.length, 2); + assert.equal(smc.sources[0], 'http://example.com/bar.js'); + assert.equal(smc.sources[1], 'http://example.com/baz.js'); + assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); + + var pos = smc.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + assert.equal(pos.source, 'http://example.com/bar.js'); + assert.equal(pos.name, null); + + pos = smc.generatedPositionFor({ + line: 1, + column: 1, + source: 'http://example.com/bar.js' + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + pos = smc.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + assert.equal(pos.source, 'http://example.com/baz.js'); + assert.equal(pos.name, 'dirtMcGirt'); + + pos = smc.generatedPositionFor({ + line: 2, + column: 2, + source: 'http://example.com/baz.js' + }); + assert.equal(pos.line, 4); + assert.equal(pos.column, 4); + }; +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 000000000..ba292f548 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,417 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; + + exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: 'a.js', + name: 'foo' + }); + map.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 4, column: 4 }, + source: 'a.js', + name: 'foo' + }); + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: ['foo'], + mappings: 'CACEA;;GAEEA' + }); + }; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 000000000..6e0eca82d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,365 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }; + + exports['test .fromStringWithSourceMap()'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }; + + exports['test .fromStringWithSourceMap() empty map'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }; + + exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + "(function() {\n", + " var Test = {};\n", + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n", + "}());\n", + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }; + + exports['test .fromStringWithSourceMap() merging duplicate mappings'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function"), + new SourceNode(1, 0, "a.js", "() {\n"), + " ", + new SourceNode(1, 0, "a.js", "var Test = "), + new SourceNode(1, 0, "b.js", "{};\n"), + new SourceNode(2, 0, "b.js", "Test"), + new SourceNode(2, 0, "b.js", ".A", "A"), + new SourceNode(2, 20, "b.js", " = { value: 1234 };\n", "A"), + "}());\n", + "/* Generated Source */" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 2 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 13 }, + source: 'b.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'b.js', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 4 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 6 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 20 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, correctMap, inputMap); + }; + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js new file mode 100644 index 000000000..288046bfa --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,161 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, + "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.npmignore b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.npmignore new file mode 100644 index 000000000..3e56974b7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.npmignore @@ -0,0 +1,14 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz +pids +logs +results +npm-debug.log +node_modules +/test/output.js diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.travis.yml b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.travis.yml new file mode 100644 index 000000000..9a61f6bd7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/LICENSE b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/LICENSE new file mode 100644 index 000000000..dfb0b19ea --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013 Forbes Lindesay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/README.md b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/README.md new file mode 100644 index 000000000..99685da2b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/README.md @@ -0,0 +1,15 @@ +# uglify-to-browserify + +A transform to make UglifyJS work in browserify. + +[![Build Status](https://travis-ci.org/ForbesLindesay/uglify-to-browserify.png?branch=master)](https://travis-ci.org/ForbesLindesay/uglify-to-browserify) +[![Dependency Status](https://gemnasium.com/ForbesLindesay/uglify-to-browserify.png)](https://gemnasium.com/ForbesLindesay/uglify-to-browserify) +[![NPM version](https://badge.fury.io/js/uglify-to-browserify.png)](http://badge.fury.io/js/uglify-to-browserify) + +## Installation + + npm install uglify-to-browserify + +## License + + MIT \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/index.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/index.js new file mode 100644 index 000000000..11cb627ba --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/index.js @@ -0,0 +1,46 @@ +'use strict' + +var fs = require('fs') +var PassThrough = require('stream').PassThrough +var Transform = require('stream').Transform + +if (typeof Transform === 'undefined') { + throw new Error('UglifyJS only supports browserify when using node >= 0.10.x') +} + +var cache = {} +module.exports = transform +function transform(file) { + if (!/tools\/node\.js$/.test(file.replace(/\\/g,'/'))) return new PassThrough(); + if (cache[file]) return makeStream(cache[file]) + var uglify = require(file) + var src = 'var sys = require("util");\nvar MOZ_SourceMap = require("source-map");\nvar UglifyJS = exports;\n' + uglify.FILES.map(function (path) { return fs.readFileSync(path, 'utf8') }).join('\n') + + var ast = uglify.parse(src) + ast.figure_out_scope() + + var variables = ast.variables + .map(function (node, name) { + return name + }) + + src += '\n\n' + variables.map(function (v) { return 'exports.' + v + ' = ' + v + ';' }).join('\n') + '\n\n' + + src += 'exports.AST_Node.warn_function = function (txt) { if (typeof console != "undefined" && typeof console.warn === "function") console.warn(txt) }\n\n' + + src += 'exports.minify = ' + uglify.minify.toString() + ';\n\n' + src += 'exports.describe_ast = ' + uglify.describe_ast.toString() + ';' + + cache[file] = src + return makeStream(src); +} + +function makeStream(src) { + var res = new Transform(); + res._transform = function (chunk, encoding, callback) { callback() } + res._flush = function (callback) { + res.push(src) + callback() + } + return res; +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/package.json new file mode 100644 index 000000000..1e85cb05a --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/package.json @@ -0,0 +1,33 @@ +{ + "name": "uglify-to-browserify", + "version": "1.0.1", + "description": "A transform to make UglifyJS work in browserify.", + "keywords": [], + "dependencies": {}, + "devDependencies": { + "uglify-js": "~2.4.0", + "source-map": "~0.1.27" + }, + "scripts": { + "test": "node test/index.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/uglify-to-browserify.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "readme": "# uglify-to-browserify\r\n\r\nA transform to make UglifyJS work in browserify.\r\n\r\n[![Build Status](https://travis-ci.org/ForbesLindesay/uglify-to-browserify.png?branch=master)](https://travis-ci.org/ForbesLindesay/uglify-to-browserify)\r\n[![Dependency Status](https://gemnasium.com/ForbesLindesay/uglify-to-browserify.png)](https://gemnasium.com/ForbesLindesay/uglify-to-browserify)\r\n[![NPM version](https://badge.fury.io/js/uglify-to-browserify.png)](http://badge.fury.io/js/uglify-to-browserify)\r\n\r\n## Installation\r\n\r\n npm install uglify-to-browserify\r\n\r\n## License\r\n\r\n MIT", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/ForbesLindesay/uglify-to-browserify/issues" + }, + "_id": "uglify-to-browserify@1.0.1", + "dist": { + "shasum": "8871cc4e7dace23bfab55f3105cd98d51bacb5d5" + }, + "_from": "uglify-to-browserify@~1.0.0", + "_resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.1.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/test/index.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/test/index.js new file mode 100644 index 000000000..411789422 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/node_modules/uglify-to-browserify/test/index.js @@ -0,0 +1,22 @@ +var fs = require('fs') +var br = require('../') +var test = fs.readFileSync(require.resolve('uglify-js/test/run-tests.js'), 'utf8') + .replace(/^#.*\n/, '') + +var transform = br(require.resolve('uglify-js')) +transform.pipe(fs.createWriteStream(__dirname + '/output.js')) + .on('close', function () { + Function('module,require', test)({ + filename: require.resolve('uglify-js/test/run-tests.js') + }, + function (name) { + if (name === '../tools/node') { + return require('./output.js') + } else if (/^[a-z]+$/.test(name)) { + return require(name) + } else { + throw new Error('I didn\'t expect you to require ' + name) + } + }) + }) +transform.end(fs.readFileSync(require.resolve('uglify-js'), 'utf8')) \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/package.json b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/package.json new file mode 100644 index 000000000..1ee4287f0 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/package.json @@ -0,0 +1,49 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.4.3", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "url": "http://lisperator.net/" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + }, + "dependencies": { + "async": "~0.2.6", + "source-map": "~0.1.7", + "optimist": "~0.3.5", + "uglify-to-browserify": "~1.0.0" + }, + "browserify": { + "transform": [ + "uglify-to-browserify" + ] + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "UglifyJS 2\n==========\n[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2)\n\nUglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.\n\nThis page documents the command line utility. For\n[API and internals documentation see my website](http://lisperator.net/uglifyjs/).\nThere's also an\n[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,\nChrome and probably Safari).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n npm install uglify-js\n\nFrom Git:\n\n git clone git://github.com/mishoo/UglifyJS2.git\n cd UglifyJS2\n npm link .\n\nUsage\n-----\n\n uglifyjs [input files] [options]\n\nUglifyJS2 can take multiple input files. It's recommended that you pass the\ninput files first, then pass the options. UglifyJS will parse input files\nin sequence and apply any compression options. The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf you want to read from STDIN instead, pass a single dash instead of input\nfiles.\n\nThe available options are:\n\n```\n --source-map Specify an output file where to generate source map.\n [string]\n --source-map-root The path to the original source to be included in the\n source map. [string]\n --source-map-url The path to the source map to be added in //#\n sourceMappingURL. Defaults to the value passed with\n --source-map. [string]\n --in-source-map Input source map, useful if you're compressing JS that was\n generated from some other original code.\n --screw-ie8 Pass this flag if you don't care about full compliance\n with Internet Explorer 6-8 quirks (by default UglifyJS\n will try to be IE-proof). [boolean]\n --expr Parse a single expression, rather than a program (for\n parsing JSON) [boolean]\n -p, --prefix Skip prefix for original filenames that appear in source\n maps. For example -p 3 will drop 3 directories from file\n names and ensure they are relative paths. You can also\n specify -p relative, which will make UglifyJS figure out\n itself the relative paths between original sources, the\n source map and the output file. [string]\n -o, --output Output file (default STDOUT).\n -b, --beautify Beautify output/specify output options. [string]\n -m, --mangle Mangle names/pass mangler options. [string]\n -r, --reserved Reserved names to exclude from mangling.\n -c, --compress Enable compressor/pass compressor options. Pass options\n like -c hoist_vars=false,if_return=false. Use -c with no\n argument to use the default compression options. [string]\n -d, --define Global definitions [string]\n -e, --enclose Embed everything in a big function, with a configurable\n parameter/argument list. [string]\n --comments Preserve copyright comments in the output. By default this\n works like Google Closure, keeping JSDoc-style comments\n that contain \"@license\" or \"@preserve\". You can optionally\n pass one of the following arguments to this flag:\n - \"all\" to keep all comments\n - a valid JS regexp (needs to start with a slash) to keep\n only comments that match.\n Note that currently not *all* comments can be kept when\n compression is on, because of dead code removal or\n cascading statements into sequences. [string]\n --preamble Preamble to prepend to the output. You can use this to\n insert a comment, for example for licensing information.\n This will not be parsed, but the source map will adjust\n for its presence.\n --stats Display operations run time on STDERR. [boolean]\n --acorn Use Acorn for parsing. [boolean]\n --spidermonkey Assume input files are SpiderMonkey AST format (as JSON).\n [boolean]\n --self Build itself (UglifyJS2) as a library (implies\n --wrap=UglifyJS --export-all) [boolean]\n --wrap Embed everything in a big function, making the “exports”\n and “global” variables available. You need to pass an\n argument to this option to specify the name that your\n module will take when included in, say, a browser.\n [string]\n --export-all Only used when --wrap, this tells UglifyJS to add code to\n automatically export all globals. [boolean]\n --lint Display some scope warnings [boolean]\n -v, --verbose Verbose [boolean]\n -V, --version Print version number and exit. [boolean]\n```\n\nSpecify `--output` (`-o`) to declare the output file. Otherwise the output\ngoes to STDOUT.\n\n## Source map options\n\nUglifyJS2 can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript. To get a source map, pass\n`--source-map output.js.map` (full path to the file where you want the\nsource map dumped).\n\nAdditionally you might need `--source-map-root` to pass the URL where the\noriginal files can be found. In case you are passing full paths to input\nfiles to UglifyJS, you can use `--prefix` (`-p`) to specify the number of\ndirectories to drop from the path prefix when declaring files in the source\nmap.\n\nFor example:\n\n uglifyjs /home/doe/work/foo/src/js/file1.js \\\n /home/doe/work/foo/src/js/file2.js \\\n -o foo.min.js \\\n --source-map foo.min.js.map \\\n --source-map-root http://foo.com/src \\\n -p 5 -c -m\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`. The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript). UglifyJS has an\noption to take an input source map. Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature you need to pass `--in-source-map\n/path/to/input/source.map`. Normally the input source map should also point\nto the file containing the generated JS, so if that's correct you can omit\ninput files from the command line.\n\n## Mangler options\n\nTo enable the mangler you need to pass `--mangle` (`-m`). The following\n(comma-separated) options are supported:\n\n- `sort` — to assign shorter names to most frequently used variables. This\n saves a few hundred bytes on jQuery before gzip, but the output is\n _bigger_ after gzip (and seems to happen for other libraries I tried it\n on) therefore it's not enabled by default.\n\n- `toplevel` — mangle names declared in the toplevel scope (disabled by\n default).\n\n- `eval` — mangle names visible in scopes where `eval` or `when` are used\n (disabled by default).\n\nWhen mangling is enabled but you want to prevent certain names from being\nmangled, you can declare those names with `--reserved` (`-r`) — pass a\ncomma-separated list of names. For example:\n\n uglifyjs ... -m -r '$,require,exports'\n\nto prevent the `require`, `exports` and `$` names from being changed.\n\n## Compressor options\n\nYou need to pass `--compress` (`-c`) to enable the compressor. Optionally\nyou can pass a comma-separated list of options. Options are in the form\n`foo=bar`, or just `foo` (the latter implies a boolean option that you want\nto set `true`; it's effectively a shortcut for `foo=true`).\n\n- `sequences` -- join consecutive simple statements using the comma operator\n\n- `properties` -- rewrite property access using the dot notation, for\n example `foo[\"bar\"] → foo.bar`\n\n- `dead_code` -- remove unreachable code\n\n- `drop_debugger` -- remove `debugger;` statements\n\n- `unsafe` (default: false) -- apply \"unsafe\" transformations (discussion below)\n\n- `conditionals` -- apply optimizations for `if`-s and conditional\n expressions\n\n- `comparisons` -- apply certain optimizations to binary nodes, for example:\n `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,\n e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n\n- `evaluate` -- attempt to evaluate constant expressions\n\n- `booleans` -- various optimizations for boolean context, for example `!!a\n ? b : c → a ? b : c`\n\n- `loops` -- optimizations for `do`, `while` and `for` loops when we can\n statically determine the condition\n\n- `unused` -- drop unreferenced functions and variables\n\n- `hoist_funs` -- hoist function declarations\n\n- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`\n by default because it seems to increase the size of the output in general)\n\n- `if_return` -- optimizations for if/return and if/continue\n\n- `join_vars` -- join consecutive `var` statements\n\n- `cascade` -- small optimization for sequences, transform `x, x` into `x`\n and `x = something(), x` into `x = something()`\n\n- `warnings` -- display warnings when dropping unreachable code or unused\n declarations etc.\n\n- `negate_iife` -- negate \"Immediately-Called Function Expressions\"\n where the return value is discarded, to avoid the parens that the\n code generator would insert.\n\n- `pure_getters` -- the default is `false`. If you pass `true` for\n this, UglifyJS will assume that object property access\n (e.g. `foo.bar` or `foo[\"bar\"]`) doesn't have any side effects.\n\n- `pure_funcs` -- default `null`. You can pass an array of names and\n UglifyJS will assume that those functions do not produce side\n effects. DANGER: will not check if the name is redefined in scope.\n An example case here, for instance `var q = Math.floor(a/b)`. If\n variable `q` is not used elsewhere, UglifyJS will drop it, but will\n still keep the `Math.floor(a/b)`, not knowing what it does. You can\n pass `pure_funcs: [ 'Math.floor' ]` to let it know that this\n function won't produce any side effect, in which case the whole\n statement would get discarded. The current implementation adds some\n overhead (compression will be slower).\n\n### The `unsafe` option\n\nIt enables some transformations that *might* break code logic in certain\ncontrived cases, but should be fine for most code. You might want to try it\non your own code, it should reduce the minified size. Here's what happens\nwhen this flag is on:\n\n- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]`\n- `new Object()` → `{}`\n- `String(exp)` or `exp.toString()` → `\"\" + exp`\n- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`\n- `typeof foo == \"undefined\"` → `foo === void 0`\n- `void 0` → `undefined` (if there is a variable named \"undefined\" in\n scope; we do it because the variable name will be mangled, typically\n reduced to a single character).\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope). For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n```javascript\nif (DEBUG) {\n\tconsole.log(\"debug stuff\");\n}\n```\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build. For example you can have a\n`build/defines.js` file with the following:\n```javascript\nconst DEBUG = false;\nconst PRODUCTION = true;\n// etc.\n```\n\nand build your code like this:\n\n uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual. The possible downside of this approach is that the build\nwill contain the `const` declarations.\n\n\n## Beautifier options\n\nThe code generator tries to output shortest code possible by default. In\ncase you want beautified output, pass `--beautify` (`-b`). Optionally you\ncan pass additional arguments that control the code output:\n\n- `beautify` (default `true`) -- whether to actually beautify the output.\n Passing `-b` will set this to true, but you might need to pass `-b` even\n when you want to generate minified code, in order to specify additional\n arguments, so you can use `-b beautify=false` to override it.\n- `indent-level` (default 4)\n- `indent-start` (default 0) -- prefix all lines by that many spaces\n- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal\n objects\n- `space-colon` (default `true`) -- insert a space after the colon signs\n- `ascii-only` (default `false`) -- escape Unicode characters in strings and\n regexps\n- `inline-script` (default `false`) -- escape the slash in occurrences of\n `= (x = f(…)) + * + * For example, let the equation be: + * (a = parseInt('100')) <= a + * + * If a was an integer and has the value of 99, + * (a = parseInt('100')) <= a → 100 <= 100 → true + * + * When transformed incorrectly: + * a >= (a = parseInt('100')) → 99 >= 100 → false + */ + +tranformation_sort_order_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) == a } + expect: { (a = parseInt('100')) == a } +} + +tranformation_sort_order_unequal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) != a } + expect: { (a = parseInt('100')) != a } +} + +tranformation_sort_order_lesser_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) <= a } + expect: { (a = parseInt('100')) <= a } +} +tranformation_sort_order_greater_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) >= a } + expect: { (a = parseInt('100')) >= a } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-22.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-22.js new file mode 100644 index 000000000..a8b7bc600 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-22.js @@ -0,0 +1,17 @@ +return_with_no_value_in_if_body: { + options = { conditionals: true }; + input: { + function foo(bar) { + if (bar) { + return; + } else { + return 1; + } + } + } + expect: { + function foo (bar) { + return bar ? void 0 : 1; + } + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-267.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-267.js new file mode 100644 index 000000000..7233d9f18 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-267.js @@ -0,0 +1,11 @@ +issue_267: { + options = { comparisons: true }; + input: { + x = a % b / b * c * 2; + x = a % b * 2 + } + expect: { + x = a % b / b * c * 2; + x = a % b * 2; + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-269.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-269.js new file mode 100644 index 000000000..70e82d080 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-269.js @@ -0,0 +1,68 @@ +issue_269_1: { + options = {unsafe: true}; + input: { + f( + String(x), + Number(x), + Boolean(x), + + String(), + Number(), + Boolean() + ); + } + expect: { + f( + x + '', +x, !!x, + '', 0, false + ); + } +} + +issue_269_dangers: { + options = {unsafe: true}; + input: { + f( + String(x, x), + Number(x, x), + Boolean(x, x) + ); + } + expect: { + f(String(x, x), Number(x, x), Boolean(x, x)); + } +} + +issue_269_in_scope: { + options = {unsafe: true}; + input: { + var String, Number, Boolean; + f( + String(x), + Number(x, x), + Boolean(x) + ); + } + expect: { + var String, Number, Boolean; + f(String(x), Number(x, x), Boolean(x)); + } +} + +strings_concat: { + options = {unsafe: true}; + input: { + f( + String(x + 'str'), + String('str' + x), + String(x + 5) + ); + } + expect: { + f( + x + 'str', + 'str' + x, + x + '5' + ); + } +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-44.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-44.js new file mode 100644 index 000000000..7a972f9ea --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-44.js @@ -0,0 +1,31 @@ +issue_44_valid_ast_1: { + options = { unused: true }; + input: { + function a(b) { + for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + var i = 0; + for (b.qoo(); ; i++); + } + } +} + +issue_44_valid_ast_2: { + options = { unused: true }; + input: { + function a(b) { + if (foo) for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + if (foo) { + var i = 0; + for (b.qoo(); ; i++); + } + } + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-59.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-59.js new file mode 100644 index 000000000..82b388067 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/issue-59.js @@ -0,0 +1,30 @@ +keep_continue: { + options = { + dead_code: true, + evaluate: true + }; + input: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } + expect: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/labels.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/labels.js new file mode 100644 index 000000000..044b7a7ea --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/labels.js @@ -0,0 +1,163 @@ +labels_1: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) break out; + console.log("bar"); + } + }; + expect: { + foo || console.log("bar"); + } +} + +labels_2: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) print("stuff"); + else break out; + console.log("here"); + } + }; + expect: { + if (foo) { + print("stuff"); + console.log("here"); + } + } +} + +labels_3: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + for (var i = 0; i < 5; ++i) { + if (i < 3) continue; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_4: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: for (var i = 0; i < 5; ++i) { + if (i < 3) continue out; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_5: { + options = { if_return: true, conditionals: true, dead_code: true }; + // should keep the break-s in the following + input: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + }; + expect: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + } +} + +labels_6: { + input: { + out: break out; + }; + expect: {} +} + +labels_7: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + continue; + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_8: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + break; + } + }; + expect: { + while (foo) { + x(); + y(); + break; + } + } +} + +labels_9: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + continue out; + z(); + k(); + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_10: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + break out; + z(); + k(); + } + }; + expect: { + out: while (foo) { + x(); + y(); + break out; + } + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/loops.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/loops.js new file mode 100644 index 000000000..cdf1f045d --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/loops.js @@ -0,0 +1,123 @@ +while_becomes_for: { + options = { loops: true }; + input: { + while (foo()) bar(); + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_break_1: { + options = { loops: true }; + input: { + for (;;) + if (foo()) break; + } + expect: { + for (; !foo();); + } +} + +drop_if_break_2: { + options = { loops: true }; + input: { + for (;bar();) + if (foo()) break; + } + expect: { + for (; bar() && !foo();); + } +} + +drop_if_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && !foo();) { + stuff1(); + stuff2(); + } + } +} + +drop_if_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), !foo());) z(), k(); + } +} + +drop_if_else_break_1: { + options = { loops: true }; + input: { + for (;;) if (foo()) bar(); else break; + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_else_break_2: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + } + } + expect: { + for (; bar() && foo();) baz(); + } +} + +drop_if_else_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && foo();) { + baz(); + stuff1(); + stuff2(); + } + } +} + +drop_if_else_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) baz(); + else break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), foo());) baz(), z(), k(); + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/negate-iife.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/negate-iife.js new file mode 100644 index 000000000..0362ffce3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/negate-iife.js @@ -0,0 +1,76 @@ +negate_iife_1: { + options = { + negate_iife: true + }; + input: { + (function(){ stuff() })(); + } + expect: { + !function(){ stuff() }(); + } +} + +negate_iife_2: { + options = { + negate_iife: true + }; + input: { + (function(){ return {} })().x = 10; // should not transform this one + } + expect: { + (function(){ return {} })().x = 10; + } +} + +negate_iife_3: { + options = { + negate_iife: true, + }; + input: { + (function(){ return true })() ? console.log(true) : console.log(false); + } + expect: { + !function(){ return true }() ? console.log(false) : console.log(true); + } +} + +negate_iife_3: { + options = { + negate_iife: true, + sequences: true + }; + input: { + (function(){ return true })() ? console.log(true) : console.log(false); + (function(){ + console.log("something"); + })(); + } + expect: { + !function(){ return true }() ? console.log(false) : console.log(true), function(){ + console.log("something"); + }(); + } +} + +negate_iife_4: { + options = { + negate_iife: true, + sequences: true, + conditionals: true, + }; + input: { + if ((function(){ return true })()) { + console.log(true); + } else { + console.log(false); + } + (function(){ + console.log("something"); + })(); + } + expect: { + !function(){ return true }() ? console.log(false) : console.log(true), function(){ + console.log("something"); + }(); + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/properties.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/properties.js new file mode 100644 index 000000000..85045961e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/properties.js @@ -0,0 +1,54 @@ +keep_properties: { + options = { + properties: false + }; + input: { + a["foo"] = "bar"; + } + expect: { + a["foo"] = "bar"; + } +} + +dot_properties: { + options = { + properties: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } + expect: { + a.foo = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } +} + +dot_properties_es5: { + options = { + properties: true, + screw_ie8: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + } + expect: { + a.foo = "bar"; + a.if = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/sequences.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/sequences.js new file mode 100644 index 000000000..466957144 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/sequences.js @@ -0,0 +1,163 @@ +make_sequences_1: { + options = { + sequences: true + }; + input: { + foo(); + bar(); + baz(); + } + expect: { + foo(),bar(),baz(); + } +} + +make_sequences_2: { + options = { + sequences: true + }; + input: { + if (boo) { + foo(); + bar(); + baz(); + } else { + x(); + y(); + z(); + } + } + expect: { + if (boo) foo(),bar(),baz(); + else x(),y(),z(); + } +} + +make_sequences_3: { + options = { + sequences: true + }; + input: { + function f() { + foo(); + bar(); + return baz(); + } + function g() { + foo(); + bar(); + throw new Error(); + } + } + expect: { + function f() { + return foo(), bar(), baz(); + } + function g() { + throw foo(), bar(), new Error(); + } + } +} + +make_sequences_4: { + options = { + sequences: true + }; + input: { + x = 5; + if (y) z(); + + x = 5; + for (i = 0; i < 5; i++) console.log(i); + + x = 5; + for (; i < 5; i++) console.log(i); + + x = 5; + switch (y) {} + + x = 5; + with (obj) {} + } + expect: { + if (x = 5, y) z(); + for (x = 5, i = 0; i < 5; i++) console.log(i); + for (x = 5; i < 5; i++) console.log(i); + switch (x = 5, y) {} + with (x = 5, obj); + } +} + +lift_sequences_1: { + options = { sequences: true }; + input: { + foo = !(x(), y(), bar()); + } + expect: { + x(), y(), foo = !bar(); + } +} + +lift_sequences_2: { + options = { sequences: true, evaluate: true }; + input: { + foo.x = (foo = {}, 10); + bar = (bar = {}, 10); + } + expect: { + foo.x = (foo = {}, 10), + bar = {}, bar = 10; + } +} + +lift_sequences_3: { + options = { sequences: true, conditionals: true }; + input: { + x = (foo(), bar(), baz()) ? 10 : 20; + } + expect: { + foo(), bar(), x = baz() ? 10 : 20; + } +} + +lift_sequences_4: { + options = { side_effects: true }; + input: { + x = (foo, bar, baz); + } + expect: { + x = baz; + } +} + +for_sequences: { + options = { sequences: true }; + input: { + // 1 + foo(); + bar(); + for (; false;); + // 2 + foo(); + bar(); + for (x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } + expect: { + // 1 + for (foo(), bar(); false;); + // 2 + for (foo(), bar(), x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/switch.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/switch.js new file mode 100644 index 000000000..62e39cf7b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/switch.js @@ -0,0 +1,260 @@ +constant_switch_1: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1+1) { + case 1: foo(); break; + case 1+1: bar(); break; + case 1+1+1: baz(); break; + } + } + expect: { + bar(); + } +} + +constant_switch_2: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + } + } + expect: { + foo(); + bar(); + } +} + +constant_switch_3: { + options = { dead_code: true, evaluate: true }; + input: { + switch (10) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + default: + def(); + } + } + expect: { + def(); + } +} + +constant_switch_4: { + options = { dead_code: true, evaluate: true }; + input: { + switch (2) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + bar(); + def(); + } +} + +constant_switch_5: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + // the break inside the if ruins our job + // we can still get rid of irrelevant cases. + switch (1) { + case 1: + x(); + if (foo) break; + y(); + } + // XXX: we could optimize this better by inventing an outer + // labeled block, but that's kinda tricky. + } +} + +constant_switch_6: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + y(); + bar(); + } + } +} + +constant_switch_7: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} + +drop_default_1: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +drop_default_2: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); break; + default: + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +keep_default: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + something(); + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + default: + something(); + } + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/typeof.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/typeof.js new file mode 100644 index 000000000..cefdd43c2 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/compress/typeof.js @@ -0,0 +1,25 @@ +typeof_evaluation: { + options = { + evaluate: true + }; + input: { + a = typeof 1; + b = typeof 'test'; + c = typeof []; + d = typeof {}; + e = typeof /./; + f = typeof false; + g = typeof function(){}; + h = typeof undefined; + } + expect: { + a='number'; + b='string'; + c=typeof[]; + d=typeof{}; + e=typeof/./; + f='boolean'; + g='function'; + h='undefined'; + } +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/run-tests.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/run-tests.js new file mode 100755 index 000000000..f8e88d480 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,179 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); +var failures = 0; +var failed_files = {}; + +run_compress_tests(); +if (failures) { + sys.error("\n!!! Failed " + failures + " test cases."); + sys.error("!!! " + Object.keys(failed_files).join(", ")); + process.exit(1); +} + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + failures++; + failed_files[file] = 1; + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/node_modules/grunt-contrib-uglify/node_modules/uglify-js/tools/node.js b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/tools/node.js new file mode 100644 index 000000000..614e083d1 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/node_modules/uglify-js/tools/node.js @@ -0,0 +1,167 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + UglifyJS.base54.reset(); + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/node_modules/grunt-contrib-uglify/package.json b/node_modules/grunt-contrib-uglify/package.json new file mode 100644 index 000000000..b70d8f797 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/package.json @@ -0,0 +1,68 @@ +{ + "name": "grunt-contrib-uglify", + "description": "Minify files with UglifyJS.", + "version": "0.2.7", + "homepage": "https://github.com/gruntjs/grunt-contrib-uglify", + "author": { + "name": "Grunt Team", + "url": "http://gruntjs.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/gruntjs/grunt-contrib-uglify.git" + }, + "bugs": { + "url": "https://github.com/gruntjs/grunt-contrib-uglify/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/gruntjs/grunt-contrib-uglify/blob/master/LICENSE-MIT" + } + ], + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "uglify-js": "~2.4.0", + "grunt-lib-contrib": "~0.6.1" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.6.3", + "grunt-contrib-nodeunit": "~0.2.0", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-internal": "~0.4.2", + "grunt": "~0.4.0" + }, + "peerDependencies": { + "grunt": "~0.4.0" + }, + "keywords": [ + "gruntplugin" + ], + "contributors": [ + { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com" + }, + { + "name": "Tyler Kellen", + "url": "http://goingslowly.com" + }, + { + "name": "Jarrod Overson", + "url": "http://jarrodoverson.com" + } + ], + "readme": "# grunt-contrib-uglify v0.2.6 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-uglify.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-uglify)\n\n> Minify files with UglifyJS.\n\n\n\n## Getting Started\nThis plugin requires Grunt `~0.4.0`\n\nIf you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:\n\n```shell\nnpm install grunt-contrib-uglify --save-dev\n```\n\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\n\n```js\ngrunt.loadNpmTasks('grunt-contrib-uglify');\n```\n\n\n\n\n## Uglify task\n_Run this task with the `grunt uglify` command._\n\nTask targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide.\n### Options\n\nThis task primarily delegates to [UglifyJS2][], so please consider the [UglifyJS documentation][] as required reading for advanced configuration.\n\n[UglifyJS2]: https://github.com/mishoo/UglifyJS2\n[UglifyJS documentation]: http://lisperator.net/uglifyjs/\n\n#### mangle\nType: `Boolean` `Object`\nDefault: `{}`\n\nTurn on or off mangling with default options. If an `Object` is specified, it is passed directly to `ast.mangle_names()` *and* `ast.compute_char_frequency()` (mimicking command line behavior).\n\n#### compress\nType: `Boolean` `Object`\nDefault: `{}`\n\nTurn on or off source compression with default options. If an `Object` is specified, it is passed as options to `UglifyJS.Compressor()`.\n\n#### beautify\nType: `Boolean` `Object`\nDefault: `false`\n\nTurns on beautification of the generated source code. An `Object` will be merged and passed with the options sent to `UglifyJS.OutputStream()`\n\n#### report\nChoices: `false` `'min'` `'gzip'`\nDefault: `false`\n\nEither do not report anything, report only minification result, or report minification and gzip results. This is useful to see exactly how well Uglify is performing, but using `'gzip'` can add 5-10x runtime task execution.\n\nExample ouput using `'gzip'`:\n\n```\nOriginal: 198444 bytes.\nMinified: 101615 bytes.\nGzipped: 20084 bytes.\n```\n\n#### sourceMap\nType: `String` `Function`\nDefault: `undefined`\n\nThe location to output the sourcemap. If a function is provided, the uglify destination is passed as the argument\nand the return value will be used as the sourceMap name.\n\n#### sourceMapRoot\nType: `String`\nDefault: `undefined`\n\nThe location where your source files can be found. This sets the sourceRoot field in the source map.\n\n#### sourceMapIn\nType: `String` `Function`\nDefault: `undefined`\n\nThe location of an input source map from an earlier compilation, e.g. from CoffeeScript. If a function is provided, the\nuglify source is passed as the argument and the return value will be used as the sourceMap name. This only makes sense\nwhen there's one source file.\n\n#### sourceMappingURL\nType: `String` `Function`\nDefault: `undefined`\n\nThe location of your sourcemap. Defaults to the location you use for sourceMap, override if you need finer control. Provide\na function to dynamically generate the sourceMappingURL based off the destination.\n\n#### sourceMapPrefix\nType: `Number`\nDefault: `undefined`\n\nThe number of directories to drop from the path prefix when declaring files in the source map.\n\n###### enclose\nType: `Object`\nDefault: `undefined`\n\nWrap all of the code in a closure with a configurable arguments/parameters list.\nEach key-value pair in the `enclose` object is effectively an argument-parameter pair.\n\n#### wrap\nType: `String`\nDefault: `undefined`\n\nWrap all of the code in a closure, an easy way to make sure nothing is leaking.\nFor variables that need to be public `exports` and `global` variables are made available.\nThe value of wrap is the global variable exports will be available as.\n\n#### exportAll\nType: `Boolean`\nDefault: `false`\n\nWhen using `wrap` this will make all global functions and variables available via the export variable.\n\n#### preserveComments\nType: `Boolean` `String` `Function`\nDefault: `undefined`\nOptions: `false` `'all'` `'some'`\n\nTurn on preservation of comments.\n\n- `false` will strip all comments\n- `'all'` will preserve all comments in code blocks that have not been squashed or dropped\n- `'some'` will preserve all comments that start with a bang (`!`) or include a closure compiler style directive (`@preserve` `@license` `@cc_on`)\n- `Function` specify your own comment preservation function. You will be passed the current node and the current comment and are expected to return either `true` or `false`\n\n#### banner\nType: `String`\nDefault: empty string\n\nThis string will be prepended to the beginning of the minified output. It is processed using [grunt.template.process][], using the default options.\n\n#### footer\nType: `String`\nDefault: empty string\n\nThis string will be append to the end of the minified output. It is processed using [grunt.template.process][], using the default options.\n\n_(Default processing options are explained in the [grunt.template.process][] documentation)_\n\n[grunt.template.process]: https://github.com/gruntjs/grunt/wiki/grunt.template#wiki-grunt-template-process\n\n\n### Usage examples\n\n#### Basic compression\n\nThis configuration will compress and mangle the input files using the default options.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n my_target: {\n files: {\n 'dest/output.min.js': ['src/input1.js', 'src/input2.js']\n }\n }\n }\n});\n```\n\n#### No mangling\n\nSpecify `mangle: false` to prevent changes to your variable and function names.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n options: {\n mangle: false\n },\n my_target: {\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n\n#### Reserved identifiers\n\nYou can specify identifiers to leave untouched with an `except` array in the `mangle` options.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n options: {\n mangle: {\n except: ['jQuery', 'Backbone']\n }\n },\n my_target: {\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n\n#### Source maps\n\nConfigure basic source map output by specifying a file path for the `sourceMap` option.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n my_target: {\n options: {\n sourceMap: 'path/to/source-map.js'\n },\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n\n#### Advanced source maps\n\nYou can specify the parameters to pass to `UglifyJS.SourceMap()` which will\nallow you to configure advanced settings.\n\nRefer to the [UglifyJS SourceMap Documentation](http://lisperator.net/uglifyjs/codegen#source-map) for more information.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n my_target: {\n options: {\n sourceMap: 'path/to/source-map.js',\n sourceMapRoot: 'http://example.com/path/to/src/', // the location to find your original source\n sourceMapIn: 'example/coffeescript-sourcemap.js', // input sourcemap from a previous compilation\n },\n files: {\n 'dest/output.min.js': ['src/input.js'],\n },\n },\n },\n});\n```\n\n\n#### Beautify\n\nSpecify `beautify: true` to beautify your code for debugging/troubleshooting purposes.\nPass an object to manually configure any other output options passed directly to `UglifyJS.OutputStream()`.\n\nSee [UglifyJS Codegen documentation](http://lisperator.net/uglifyjs/codegen) for more information.\n\n_Note that manual configuration will require you to explicitly set `beautify: true` if you want traditional, beautified output._\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n my_target: {\n options: {\n beautify: true\n },\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n },\n my_advanced_target: {\n options: {\n beautify: {\n width: 80,\n beautify: true\n }\n },\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n\n#### Banner comments\n\nIn this example, running `grunt uglify:my_target` will prepend a banner created by interpolating the `banner` template string with the config object. Here, those properties are the values imported from the `package.json` file (which are available via the `pkg` config property) plus today's date.\n\n_Note: you don't have to use an external JSON file. It's also valid to create the `pkg` object inline in the config. That being said, if you already have a JSON file, you might as well reference it._\n\n```js\n// Project configuration.\ngrunt.initConfig({\n pkg: grunt.file.readJSON('package.json'),\n uglify: {\n options: {\n banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +\n '<%= grunt.template.today(\"yyyy-mm-dd\") %> */'\n },\n my_target: {\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n\n#### Conditional compilation\n\nYou can also enable UglifyJS conditional compilation. This is commonly used to remove debug code blocks for production builds.\n\nSee [UglifyJS global definitions documentation](http://lisperator.net/uglifyjs/compress#global-defs) for more information.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n options: {\n compress: {\n global_defs: {\n \"DEBUG\": false\n },\n dead_code: true\n }\n },\n my_target: {\n files: {\n 'dest/output.min.js': ['src/input.js']\n }\n }\n }\n});\n```\n#### Compiling all files in a folder dynamically\n\nThis configuration will compress and mangle the files dynamically.\n\n```js\n// Project configuration.\ngrunt.initConfig({\n uglify: {\n my_target: {\n files: [{\n expand: true,\n cwd: 'src/js',\n src: '**/*.js',\n dest: 'dest/js'\n }]\n }\n }\n});\n```\n\n\n## Release History\n\n * 2013-11-09   v0.2.7   prepending banner if sourceMap option not set, addresses\n * 2013-11-08   v0.2.6   merged 45, 53, 85 (105 by way of duping 53) Added support for banners in uglified files with sourcemaps Updated docs\n * 2013-10-28   v0.2.5   Added warning for banners when using sourcemaps\n * 2013-09-02   v0.2.4   updated sourcemap format via /83\n * 2013-06-10   v0.2.3   added footer option\n * 2013-05-31   v0.2.2   Reverted /56 due to /58 until [chrome/239660](https://code.google.com/p/chromium/issues/detail?id=239660&q=sourcemappingurl&colspec=ID%20Pri%20M%20Iteration%20ReleaseBlock%20Cr%20Status%20Owner%20Summary%20OS%20Modified) [firefox/870361](https://bugzilla.mozilla.org/show_bug.cgi?id=870361) drop\n * 2013-05-22   v0.2.1   Bumped uglify to ~2.3.5 /55 /40 Changed sourcemappingUrl syntax /56 Disabled sorting of names for consistent mangling /44 Updated docs for sourceMapRoot /47 /25\n * 2013-03-14   v0.2.0   No longer report gzip results by default. Support `report` option.\n * 2013-01-30   v0.1.2   Added better error reporting Support for dynamic names of multiple sourcemaps\n * 2013-02-15   v0.1.1   First official release for Grunt 0.4.0.\n * 2013-01-18   v0.1.1rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.\n * 2013-01-09   v0.1.1rc5   Updating to work with grunt v0.4.0rc5. Switching back to this.files api.\n * 2012-11-28   v0.1.0   Work in progress, not yet officially released.\n\n---\n\nTask submitted by [\"Cowboy\" Ben Alman](http://benalman.com)\n\n*This file was generated on Sat Nov 09 2013 12:42:05.*\n", + "readmeFilename": "README.md", + "_id": "grunt-contrib-uglify@0.2.7", + "dist": { + "shasum": "12f7a3bfddb52d9b08565fd5e34bdec62c4b3930" + }, + "_from": "grunt-contrib-uglify@~0.2.4", + "_resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.2.7.tgz" +} diff --git a/node_modules/grunt-contrib-uglify/tasks/lib/uglify.js b/node_modules/grunt-contrib-uglify/tasks/lib/uglify.js new file mode 100644 index 000000000..36aadbf2e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/tasks/lib/uglify.js @@ -0,0 +1,158 @@ +/* + * grunt-contrib-uglify + * https://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +// External libs. +var UglifyJS = require('uglify-js'); +var fs = require('fs'); + +exports.init = function(grunt) { + var exports = {}; + + // Minify with UglifyJS. + // From https://github.com/mishoo/UglifyJS2 + // API docs at http://lisperator.net/uglifyjs/ + exports.minify = function(files, dest, options) { + options = options || {}; + + grunt.verbose.write('Minifying with UglifyJS...'); + + var topLevel = null; + var totalCode = ''; + + var outputOptions = getOutputOptions(options, dest); + var output = UglifyJS.OutputStream(outputOptions); + + // Grab and parse all source files + files.forEach(function(file){ + var code = grunt.file.read(file); + if (typeof options.sourceMapPrefix !== 'undefined') { + file = file.replace(/^\/+/, "").split(/\/+/).slice(options.sourceMapPrefix).join("/"); + } + totalCode += code; + topLevel = UglifyJS.parse(code, { + filename: file, + toplevel: topLevel + }); + }); + + // Wrap code in a common js wrapper. + if (options.wrap) { + topLevel = topLevel.wrap_commonjs(options.wrap, options.exportAll); + } + + // Wrap code in closure with configurable arguments/parameters list. + if (options.enclose) { + var argParamList = grunt.util._.map(options.enclose, function(val, key) { + return key + ':' + val; + }); + + topLevel = topLevel.wrap_enclose(argParamList); + } + + // Need to call this before we mangle or compress, + // and call after any compression or ast altering + topLevel.figure_out_scope(); + + if (options.compress !== false) { + if (options.compress.warnings !== true) { + options.compress.warnings = false; + } + var compressor = UglifyJS.Compressor(options.compress); + topLevel = topLevel.transform(compressor); + + // Need to figure out scope again after source being altered + topLevel.figure_out_scope(); + } + + if (options.mangle !== false) { + // disabled due to: + // 1) preserve stable name mangling + // 2) it increases gzipped file size, see https://github.com/mishoo/UglifyJS2#mangler-options + // // compute_char_frequency optimizes names for compression + // topLevel.compute_char_frequency(options.mangle); + + // Requires previous call to figure_out_scope + // and should always be called after compressor transform + topLevel.mangle_names(options.mangle); + } + + // Print the ast to OutputStream + topLevel.print(output); + + var min = output.get(); + + if (options.sourceMappingURL || options.sourceMap) { + min += "\n//# sourceMappingURL=" + (options.sourceMappingURL || options.sourceMap); + } + + var result = { + max: totalCode, + min: min, + sourceMap: outputOptions.source_map + }; + + grunt.verbose.ok(); + + return result; + }; + + var getOutputOptions = function(options, dest) { + var outputOptions = { + beautify: false, + source_map: null + }; + + if (options.preserveComments) { + if (options.preserveComments === 'all' || options.preserveComments === true) { + + // preserve all the comments we can + outputOptions.comments = true; + } else if (options.preserveComments === 'some') { + // preserve comments with directives or that start with a bang (!) + outputOptions.comments = /^!|@preserve|@license|@cc_on/i; + } else if (grunt.util._.isFunction(options.preserveComments)) { + + // support custom functions passed in + outputOptions.comments = options.preserveComments; + } + } + + if (options.banner && options.sourceMap) { + outputOptions.preamble = options.banner; + } + + if (options.beautify) { + if (grunt.util._.isObject(options.beautify)) { + // beautify options sent as an object are merged + // with outputOptions and passed to the OutputStream + grunt.util._.extend(outputOptions, options.beautify); + } else { + outputOptions.beautify = true; + } + } + + + if (options.sourceMap) { + var sourceMapIn; + if (options.sourceMapIn) { + sourceMapIn = grunt.file.readJSON(options.sourceMapIn); + } + outputOptions.source_map = UglifyJS.SourceMap({ + file: dest, + root: options.sourceMapRoot, + orig: sourceMapIn + }); + } + + return outputOptions; + }; + + return exports; +}; diff --git a/node_modules/grunt-contrib-uglify/tasks/uglify.js b/node_modules/grunt-contrib-uglify/tasks/uglify.js new file mode 100644 index 000000000..a8dcd2901 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/tasks/uglify.js @@ -0,0 +1,149 @@ +/* + * grunt-contrib-uglify + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Internal lib. + var contrib = require('grunt-lib-contrib').init(grunt); + var uglify = require('./lib/uglify').init(grunt); + + grunt.registerMultiTask('uglify', 'Minify files with UglifyJS.', function() { + // Merge task-specific and/or target-specific options with these defaults. + var options = this.options({ + banner: '', + footer: '', + compress: { + warnings: false + }, + mangle: {}, + beautify: false, + report: false + }); + + // Process banner. + var banner = grunt.template.process(options.banner); + var footer = grunt.template.process(options.footer); + var mapNameGenerator, mapInNameGenerator, mappingURLGenerator; + + // Iterate over all src-dest file pairs. + this.files.forEach(function(f) { + var src = f.src.filter(function(filepath) { + // Warn on and remove invalid source files (if nonull was set). + if (!grunt.file.exists(filepath)) { + grunt.log.warn('Source file "' + filepath + '" not found.'); + return false; + } else { + return true; + } + }); + + if (src.length === 0) { + grunt.log.warn('Destination (' + f.dest + ') not written because src files were empty.'); + return; + } + + // function to get the name of the sourceMap + if (typeof options.sourceMap === "function") { + mapNameGenerator = options.sourceMap; + } + + // function to get the name of the sourceMap + if (typeof options.sourceMapIn === "function") { + if (src.length !== 1) { + grunt.fail.warn('Cannot generate `sourceMapIn` for multiple source files.'); + } + mapInNameGenerator = options.sourceMapIn; + } + + // function to get the sourceMappingURL + if (typeof options.sourceMappingURL === "function") { + mappingURLGenerator = options.sourceMappingURL; + } + + // dynamically create destination sourcemap name + if (mapNameGenerator) { + try { + options.sourceMap = mapNameGenerator(f.dest); + } catch (e) { + var err = new Error('SourceMapName failed.'); + err.origError = e; + grunt.fail.warn(err); + } + } + + // dynamically create incoming sourcemap names + if (mapInNameGenerator) { + try { + options.sourceMapIn = mapInNameGenerator(src[0]); + } catch (e) { + var err = new Error('SourceMapInName failed.'); + err.origError = e; + grunt.fail.warn(err); + } + } + + // dynamically create sourceMappingURL + if (mappingURLGenerator) { + try { + options.sourceMappingURL = mappingURLGenerator(f.dest); + } catch (e) { + var err = new Error('SourceMappingURL failed.'); + err.origError = e; + grunt.fail.warn(err); + } + } + + // Minify files, warn and fail on error. + var result; + try { + result = uglify.minify(src, f.dest, options); + } catch (e) { + console.log(e); + var err = new Error('Uglification failed.'); + if (e.message) { + err.message += '\n' + e.message + '. \n'; + if (e.line) { + err.message += 'Line ' + e.line + ' in ' + src + '\n'; + } + } + err.origError = e; + grunt.log.warn('Uglifying source "' + src + '" failed.'); + grunt.fail.warn(err); + } + + // Concat minified source + footer + var output = result.min + footer; + + // Only prepend banner if uglify hasn't taken care of it as part of the preamble + if (!options.sourceMap) { + output = banner + output; + } + + // Write the destination file. + grunt.file.write(f.dest, output); + + + // Write source map + if (options.sourceMap) { + grunt.file.write(options.sourceMap, result.sourceMap); + grunt.log.writeln('Source Map "' + options.sourceMap + '" created.'); + } + + // Print a success message. + grunt.log.writeln('File "' + f.dest + '" created.'); + + // ...and report some size information. + if (options.report) { + contrib.minMaxInfo(output, result.max, options.report); + } + }); + }); + +}; diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/comments.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/comments.js new file mode 100644 index 000000000..fbb3703e5 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/comments.js @@ -0,0 +1,12 @@ +/*! + * I am a comment + */ +function foo(){return 42}// @preserve preserve +// @license license +function bar(){return 2*foo()}/* @preserve + * multiline preserve + */ +/* @license + * multiline license + */ +function baz(){return bar()*bar()} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress.js new file mode 100644 index 000000000..a9c123e1e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress.js @@ -0,0 +1 @@ +function longFunctionC(argumentC,argumentD){return longNameA+longNameB+argumentC+argumentD}var longNameA=1,longNameB=2,result=longFunctionC(3,4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle.js new file mode 100644 index 000000000..c66c512da --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle.js @@ -0,0 +1 @@ +function longFunctionC(a,b){return longNameA+longNameB+a+b}var longNameA=1,longNameB=2,result=longFunctionC(3,4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_banner.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_banner.js new file mode 100644 index 000000000..1de7a8295 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_banner.js @@ -0,0 +1,2 @@ +// banner without sourcemap +function longFunctionC(a,b){return longNameA+longNameB+a+b}var longNameA=1,longNameB=2,result=longFunctionC(3,4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_beautify.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_beautify.js new file mode 100644 index 000000000..9bcd38789 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_beautify.js @@ -0,0 +1,5 @@ +function longFunctionC(a, b) { + return longNameA + longNameB + a + b; +} + +var longNameA = 1, longNameB = 2, result = longFunctionC(3, 4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_except.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_except.js new file mode 100644 index 000000000..6830da93f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_except.js @@ -0,0 +1 @@ +function longFunctionC(argumentC,a){return longNameA+longNameB+argumentC+a}var longNameA=1,longNameB=2,result=longFunctionC(3,4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_sourcemap b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_sourcemap new file mode 100644 index 000000000..864317ae6 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/compress_mangle_sourcemap @@ -0,0 +1 @@ +{"version":3,"file":"/dev/null","sources":["test/fixtures/src/simple.js"],"names":["longFunctionC","argumentC","argumentD","longNameA","longNameB","result"],"mappings":"AAOA,QAASA,eAAcC,EAAUC,GAC/B,MAAOC,WAAYC,UAAYH,EAAYC,EAL7C,GAAIC,WAAY,EAEZC,UAAY,EAMZC,OAASL,cAAc,EAAE"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/enclose.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/enclose.js new file mode 100644 index 000000000..85dbcf820 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/enclose.js @@ -0,0 +1,8 @@ +(function(paramA, paramB) { + var longNameA = 1; + var longNameB = 2; + function longFunctionC(argumentC, argumentD) { + return longNameA + longNameB + argumentC + argumentD; + } + var result = longFunctionC(3, 4); +})(window.argA, window.argB); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/exportAll.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/exportAll.js new file mode 100644 index 000000000..d072a336e --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/exportAll.js @@ -0,0 +1 @@ +!function(exports,global){function longFunctionC(argumentC,argumentD){return longNameA+longNameB+argumentC+argumentD}global.testExport=exports;var longNameA=1,longNameB=2,result=longFunctionC(3,4);exports.longNameA=longNameA,exports.longNameB=longNameB,exports.longFunctionC=longFunctionC,exports.result=result}({},function(){return this}()); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/multifile.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multifile.js new file mode 100644 index 000000000..beb6c519c --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multifile.js @@ -0,0 +1 @@ +function longFunctionC(argumentC,argumentD){return longNameA+longNameB+argumentC+argumentD}function foo(){return 42}function bar(){return 2*foo()}function baz(){return bar()*bar()}var longNameA=1,longNameB=2,result=longFunctionC(3,4); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.js new file mode 100644 index 000000000..48e7cb939 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.js @@ -0,0 +1,2 @@ +function longFunctionC(a,b){return longNameA+longNameB+a+b}var longNameA=1,longNameB=2,result=longFunctionC(3,4); +//# sourceMappingURL=test/fixtures/expected/multiple_sourcemaps1.mapurl \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.map b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.map new file mode 100644 index 000000000..c5e3601e0 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps1.map @@ -0,0 +1 @@ +{"version":3,"file":"test/fixtures/expected/multiple_sourcemaps1.js","sources":["test/fixtures/src/simple.js"],"names":["longFunctionC","argumentC","argumentD","longNameA","longNameB","result"],"mappings":"AAOA,QAASA,eAAcC,EAAUC,GAC/B,MAAOC,WAAYC,UAAYH,EAAYC,EAL7C,GAAIC,WAAY,EAEZC,UAAY,EAMZC,OAASL,cAAc,EAAE"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.js new file mode 100644 index 000000000..4e6814b1b --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.js @@ -0,0 +1,2 @@ +function foo(){return 42}function bar(){return 2*foo()}function baz(){return bar()*bar()} +//# sourceMappingURL=test/fixtures/expected/multiple_sourcemaps2.mapurl \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.map b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.map new file mode 100644 index 000000000..18dd794e6 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/multiple_sourcemaps2.map @@ -0,0 +1 @@ +{"version":3,"file":"test/fixtures/expected/multiple_sourcemaps2.js","sources":["test/fixtures/src/comments.js"],"names":["foo","bar","baz"],"mappings":"AAGA,QAASA,OACP,MAAO,IAIT,QAASC,OACP,MAAa,GAAND,MAQT,QAASE,OACP,MAAOD,OAAMA"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemap_prefix b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemap_prefix new file mode 100644 index 000000000..0fcd10846 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemap_prefix @@ -0,0 +1 @@ +{"version":3,"file":"/dev/null","sources":["simple.js"],"names":["longFunctionC","argumentC","argumentD","longNameA","longNameB","result"],"mappings":"AAOA,QAASA,eAAcC,EAAUC,GAC/B,MAAOC,WAAYC,UAAYH,EAAYC,EAL7C,GAAIC,WAAY,EAEZC,UAAY,EAMZC,OAASL,cAAc,EAAE"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin new file mode 100644 index 000000000..49e7feb54 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin @@ -0,0 +1 @@ +{"version":3,"file":"test/fixtures/expected/sourcemapin.js","sources":["test/fixtures/src/simple2.coffee"],"names":[],"mappings":";;IAAC,YAAA,GAAA,OAAA,KAAA,KAAA,OAAA,SAAA,KAAA,MACA,QAAW,GACX,UAAW,EAGK,WAAhB,OAAS,KAGT,OAAS,SAAA,GAAA,MAAO,GAAI,GAGpB,MAAQ,EAAG,EAAG,EAAG,EAAG,GAGpB,MACG,KAAQ,KAAI,KACb,OAAQ,OACR,KAAQ,SAAA,GAAA,MAAO,GAAI,OAAO,KAG1B,KAAO,SAAA,OAAA,SAAS,MAAA,SAAA,GAAA,UAAA,UAAA,MAAA,KAAA,UAAA,MACf,MAAM,OAAQ,UAGf,mBAAsB,QAAA,MAAA,OAAtB,MAAM,cAGR,MAAA,SAAA,QAAS,IAAA,GAAT,KAAS,GAAA,EAAA,QAAyB,KAAA,OAAzB,QAAA,KAAA,GAAkB,IAAO,KAAA,IAAA,OAAA,KAAzB,KAAI,KAAM,KAAV,OAAA,SAAA,KAAA,UAAA,KAAA","sourceRoot":"http://local.host/js/"} \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin.js new file mode 100644 index 000000000..28abbe7f7 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapin.js @@ -0,0 +1,4 @@ +// Hello World + +void function(){var cubes,list,math,number,opposite,race,square;number=42,opposite=!0,opposite&&(number=-42),square=function(x){return x*x},list=[1,2,3,4,5],math={root:Math.sqrt,square:square,cube:function(x){return x*square(x)}},race=function(winner,runners){return runners=2<=arguments.length?[].slice.call(arguments,1):[],print(winner,runners)},"undefined"!=typeof elvis&&null!=elvis&&alert("I knew it!"),cubes=function(accum$){for(var num,i$=0,length$=list.length;length$>i$;++i$)num=list[i$],accum$.push(math.cube(num));return accum$}.call(this,[])}.call(this); +//# sourceMappingURL=test/fixtures/expected/sourcemapin \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapurl.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapurl.js new file mode 100644 index 000000000..930c9f47f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/sourcemapurl.js @@ -0,0 +1,2 @@ +function longFunctionC(a,b){return longNameA+longNameB+a+b}var longNameA=1,longNameB=2,result=longFunctionC(3,4); +//# sourceMappingURL=js/sourcemapurl.js.map \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/expected/wrap.js b/node_modules/grunt-contrib-uglify/test/fixtures/expected/wrap.js new file mode 100644 index 000000000..1c61f2a59 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/expected/wrap.js @@ -0,0 +1 @@ +!function(exports,global){function longFunctionC(argumentC,argumentD){return longNameA+longNameB+argumentC+argumentD}global.testExport=exports;{var longNameA=1,longNameB=2;longFunctionC(3,4)}}({},function(){return this}()); \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/src/comments.js b/node_modules/grunt-contrib-uglify/test/fixtures/src/comments.js new file mode 100644 index 000000000..32e5578f3 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/src/comments.js @@ -0,0 +1,21 @@ +/*! + * I am a comment + */ +function foo() { + return 42; +} +// @preserve preserve +// @license license +function bar() { + return foo()*2; +} +/* @preserve + * multiline preserve + */ +/* @license + * multiline license + */ +function baz() { + return bar()*bar(); +} +// end - not preserved \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/src/simple.js b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple.js new file mode 100644 index 000000000..00bc9385f --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple.js @@ -0,0 +1,15 @@ + +// Hello world, I'm a comment! + +var longNameA = 1; + +var longNameB = 2; + +function longFunctionC(argumentC,argumentD) { + return longNameA + longNameB + argumentC + argumentD; +} + +var result = longFunctionC(3,4); + +/*! I might be preserved, yay! */ + diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.coffee b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.coffee new file mode 100644 index 000000000..113aa3453 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.coffee @@ -0,0 +1,28 @@ +# Assignment: +number = 42 +opposite = true + +# Conditions: +number = -42 if opposite + +# Functions: +square = (x) -> x * x + +# Arrays: +list = [1, 2, 3, 4, 5] + +# Objects: +math = + root: Math.sqrt + square: square + cube: (x) -> x * square x + +# Splats: +race = (winner, runners...) -> + print winner, runners + +# Existence: +alert "I knew it!" if elvis? + +# Array comprehensions: +cubes = (math.cube num for num in list) \ No newline at end of file diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.js b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.js new file mode 100644 index 000000000..31fd083fa --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.js @@ -0,0 +1,39 @@ +// Generated by CoffeeScript 2.0.0-dev +void function () { + var cubes, list, math, number, opposite, race, square; + number = 42; + opposite = true; + if (opposite) + number = -42; + square = function (x) { + return x * x; + }; + list = [ + 1, + 2, + 3, + 4, + 5 + ]; + math = { + root: Math.sqrt, + square: square, + cube: function (x) { + return x * square(x); + } + }; + race = function (winner, runners) { + runners = 2 <= arguments.length ? [].slice.call(arguments, 1) : []; + return print(winner, runners); + }; + if ('undefined' !== typeof elvis && null != elvis) + alert('I knew it!'); + cubes = function (accum$) { + var num; + for (var i$ = 0, length$ = list.length; i$ < length$; ++i$) { + num = list[i$]; + accum$.push(math.cube(num)); + } + return accum$; + }.call(this, []); +}.call(this); diff --git a/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.map b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.map new file mode 100644 index 000000000..c77033cdd --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/fixtures/src/simple2.map @@ -0,0 +1 @@ +{"version":3,"file":"test/fixtures/src/simple2.coffee","sources":["test/fixtures/src/simple2.coffee"],"names":[],"mappings":"AAAC;;;EACA,MAAA,GAAW;EACX,QAAA,GAAW;EAGX,IAAgB,QAAhB,CAAA;AAAA,IAAA,MAAA,GAAS,CAAC;EAGV,MAAA,GAAS,SAAA,CAAA,CAAA,CAAA;WAAO,CAAA,CAAA,CAAA,CAAI;;EAGpB,IAAA,GAAO,CAAA;AAAA,IAAC,CAAD;AAAA,IAAI,CAAJ;AAAA,IAAO,CAAP;AAAA,IAAU,CAAV;AAAA,IAAa,CAAb;AAAA,EAAA;EAGP,IAAA,GACG,CAAA;AAAA,IAAA,IAAA,EAAQ,IAAI,KAAZ;AAAA,IACD,MAAA,EAAQ,MADP;AAAA,IAED,IAAA,EAAQ,SAAA,CAAA,CAAA,CAAA;aAAO,CAAA,CAAA,CAAA,CAAI,MAAA,CAAO,CAAP;KAFlB;AAAA,EAAA;EAKD,IAAA,GAAO,SAAA,CAAA,MAAA,EAAA,OAAA,CAAA;IAAS;WACf,KAAA,CAAM,MAAN,EAAc,OAAd;;EAGD,2BAAsB,KAAA,CAAA,EAAA,SAAA,KAAtB,CAAA;AAAA,IAAA,KAAA,CAAM,YAAN;EAGF,KAAA;;IAAS,2BAAyB,YAAzB,aAAA,CAAA,KAAA,CAAA;MAAkB,MAAO;kBAAzB,IAAI,KAAJ,CAAU,GAAV"} diff --git a/node_modules/grunt-contrib-uglify/test/uglify_test.js b/node_modules/grunt-contrib-uglify/test/uglify_test.js new file mode 100644 index 000000000..d7397b746 --- /dev/null +++ b/node_modules/grunt-contrib-uglify/test/uglify_test.js @@ -0,0 +1,58 @@ +'use strict'; + +var grunt = require('grunt'); + +var tmp = 'tmp/', + fixtures = 'test/fixtures/expected/'; + +exports.contrib_uglify = { + preuglified_files: function(test) { + + var files = [ + 'comments.js', + 'compress.js', + 'compress_mangle.js', + 'compress_mangle_banner.js', + 'compress_mangle_beautify.js', + 'compress_mangle_except.js', + 'compress_mangle_sourcemap', + 'enclose.js', + 'sourcemapurl.js', + 'multifile.js', + 'wrap.js', + 'exportAll.js', + 'sourcemap_prefix' + ]; + + test.expect(files.length); + + files.forEach(function(file){ + var actual = grunt.file.read(tmp + file); + var expected = grunt.file.read(fixtures + file); + test.equal(actual, expected, 'task output should equal ' + file); + }); + + test.done(); + }, + relative_test : function(test) { + + var files = [ + 'sourcemapin', + 'sourcemapin.js', + 'multiple_sourcemaps1.js', + 'multiple_sourcemaps1.map', + 'multiple_sourcemaps2.js', + 'multiple_sourcemaps2.map', + ]; + + test.expect(files.length); + + files.forEach(function(file){ + var actual = grunt.file.read(tmp + file).replace(tmp,'REPLACED'); + var expected = grunt.file.read(fixtures + file).replace(fixtures,'REPLACED'); + test.equal(actual, expected, 'task output should equal ' + file); + }); + + test.done(); + } +}; diff --git a/owncloudorgnew/.editorconfig b/node_modules/grunt-contrib-watch/.editorconfig similarity index 82% rename from owncloudorgnew/.editorconfig rename to node_modules/grunt-contrib-watch/.editorconfig index cf8d7fa6e..6c5424edb 100644 --- a/owncloudorgnew/.editorconfig +++ b/node_modules/grunt-contrib-watch/.editorconfig @@ -1,5 +1,4 @@ # editorconfig.org - root = true [*] @@ -8,4 +7,4 @@ indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = true +insert_final_newline = true \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/.gitattributes b/node_modules/grunt-contrib-watch/.gitattributes new file mode 100644 index 000000000..212566614 --- /dev/null +++ b/node_modules/grunt-contrib-watch/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/.jshintrc b/node_modules/grunt-contrib-watch/.jshintrc new file mode 100644 index 000000000..e0cc7bbe8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/.jshintrc @@ -0,0 +1,14 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true, + "es5": true +} \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/.npmignore b/node_modules/grunt-contrib-watch/.npmignore new file mode 100644 index 000000000..b785247e5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/.npmignore @@ -0,0 +1,3 @@ +node_modules +npm-debug.log +tmp diff --git a/node_modules/grunt-contrib-watch/.travis.yml b/node_modules/grunt-contrib-watch/.travis.yml new file mode 100644 index 000000000..57661910e --- /dev/null +++ b/node_modules/grunt-contrib-watch/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.8" + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/AUTHORS b/node_modules/grunt-contrib-watch/AUTHORS new file mode 100644 index 000000000..835393779 --- /dev/null +++ b/node_modules/grunt-contrib-watch/AUTHORS @@ -0,0 +1,21 @@ +Kyle Robinson Young (http://dontkry.com) +"Cowboy" Ben Alman (http://benalman.com) +Tyler Kellen (http://goingslowly.com) +Gong Hao +Jaime Pillora +Chris Danford +Jason San Jose +Oleg Seletsky +Jamie Stackhouse +Chris Talkington +Oliver Joseph Ash +Iskren Chernev +Joey Baker +John K. Paul +Jurie-Jan Botha +Michał Gołębiowski +Willie V +cfddream +Chris Wren +Daniel Steigerwald +Rich Trott diff --git a/node_modules/grunt-contrib-watch/CHANGELOG b/node_modules/grunt-contrib-watch/CHANGELOG new file mode 100644 index 000000000..13b2e9466 --- /dev/null +++ b/node_modules/grunt-contrib-watch/CHANGELOG @@ -0,0 +1,118 @@ +v0.5.3: + date: 2013-08-25 + changes: + - Fixed for live reload missing files. +v0.5.2: + date: 2013-08-16 + changes: + - Fixed issue running tasks after gruntfile is reloaded. + - Ignores empty file paths. +v0.5.1: + date: 2013-07-20 + changes: + - Fixed issue with options resetting. +v0.5.0: + date: 2013-07-18 + changes: + - Added target name to watch event. + - Added atBegin option to run tasks when watcher starts. + - Changed nospawn option to spawn (nospawn still available for backwards compatibility). + - Moved libs/vars into top scope to prevent re-init. + - Bumped Gaze version to ~0.4. + - Re-grab task/target options upon each task run. + - Add dateFormat option to override the date/time output upon completion. +v0.4.4: + date: 2013-05-27 + changes: + - Remove gracefully closing SIGINT. Not needed and causes problems for Windows. + - Ensure tasks are an array to not conflict with cliArgs. +v0.4.3: + date: 2013-05-11 + changes: + - Only group changed files per target to send correct files to live reload. +v0.4.2: + date: 2013-05-09 + changes: + - Fix for closing watchers. +v0.4.1: + date: 2013-05-09 + changes: + - Removed "beep" notification. + - Tasks now optional with livereload option. + - Reverted "run again" with interrupt off to fix infinite recursion issue. + - Watchers now close more properly on task run. +v0.4.0: + date: 2013-05-03 + changes: + - Option livereload to start live reload servers. + - Will reload a Gruntfile before running tasks if Gruntfile is modified. + - Option event to only trigger watch on certain events. + - Refactor watch task into separate task runs per target. + - Option forever to override grunt.fatal/warn to help keeping the watch alive with nospawn enabled. + - Emit a beep upon complete. + - Logs all watched files with verbose flag set. + - If interrupt is off, will run the tasks once more if watch triggered during a previous task run. + - tasks property is optional for use with watch event. + - Watchers properly closed when exiting. +v0.3.1: + date: 2013-02-28 + changes: + - Fix for top level options. +v0.3.0: + date: 2013-02-27 + changes: + - nospawn option added to run tasks without spawning as child processes. + - Watch emits 'watch' events upon files being triggered with grunt.event. + - Completion time in seconds and date/time shown after tasks ran. + - Negate file patterns fixed. + - Tasks debounced individually to handle simultaneous triggering for multiple targets. + - Errors handled better and viewable with --stack cli option. + - Code complexity reduced making the watch task code easier to read. +v0.2.0: + date: 2013-02-15 + changes: + - First official release for Grunt 0.4.0. +v0.2.0rc7: + date: 2013-01-18 + changes: + - Updating grunt/gruntplugin dependencies to rc6. + - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. +v0.2.0rc5: + date: 2013-01-09 + changes: + - Updating to work with grunt v0.4.0rc5. +v0.2.0a: + date: 2012-12-15 + changes: + - Conversion to grunt v0.4 conventions. + - Remove node v0.6 and grunt v0.3 support. + - Allow watch task to be renamed. + - Use grunt.util.spawn "grunt" option. + - Updated to gaze@0.3.0, forceWatchMethod option removed. +v0.1.4: + date: 2012-11-01 + changes: + - Prevent watch from spawning duplicate watch tasks +v0.1.3: + date: 2012-10-28 + changes: + - Better method to spawn the grunt bin + - Bump gaze to v0.2.0. Better handles some events and new option forceWatchMethod + - Only support Node.js >= v0.8 +v0.1.2: + date: 2012-10-17 + changes: + - Only spawn a process per task one at a time + - Add interrupt option to cancel previous spawned process + - Grunt v0.3 compatibility changes +v0.1.1: + date: 2012-10-16 + changes: + - Fallback to global grunt bin if local doesnt exist. Fatal if bin cannot be found + - Update to gaze 0.1.6 +v0.1.0: + date: 2012-10-08 + changes: + - Release watch task + - Remove spawn from helper + - Run on Grunt v0.4 diff --git a/node_modules/grunt-contrib-watch/CONTRIBUTING.md b/node_modules/grunt-contrib-watch/CONTRIBUTING.md new file mode 100644 index 000000000..5d08cc387 --- /dev/null +++ b/node_modules/grunt-contrib-watch/CONTRIBUTING.md @@ -0,0 +1 @@ +Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project. diff --git a/node_modules/grunt-contrib-watch/Gruntfile.js b/node_modules/grunt-contrib-watch/Gruntfile.js new file mode 100644 index 000000000..f14da2f5a --- /dev/null +++ b/node_modules/grunt-contrib-watch/Gruntfile.js @@ -0,0 +1,47 @@ +/* + * grunt-contrib-watch + * http://gruntjs.com/ + * + * Copyright (c) 2013 "Cowboy" Ben Alman, contributors + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'tasks/**/*.js', + '<%= nodeunit.tests %>', + ], + options: { + jshintrc: '.jshintrc', + }, + }, + watch: { + all: { + files: ['<%= jshint.all %>'], + tasks: ['jshint', 'nodeunit'], + }, + }, + nodeunit: { + tests: ['test/tasks/*_test.js'], + }, + }); + + // Dynamic alias task to nodeunit. Run individual tests with: grunt test:events + grunt.registerTask('test', function(file) { + grunt.config('nodeunit.tests', String(grunt.config('nodeunit.tests')).replace('*', file || '*')); + grunt.task.run('nodeunit'); + }); + + grunt.loadTasks('tasks'); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-internal'); + + grunt.registerTask('default', ['jshint', 'nodeunit', 'build-contrib']); +}; diff --git a/node_modules/grunt-contrib-watch/LICENSE-MIT b/node_modules/grunt-contrib-watch/LICENSE-MIT new file mode 100644 index 000000000..9edf7531b --- /dev/null +++ b/node_modules/grunt-contrib-watch/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 "Cowboy" Ben Alman, contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/README.md b/node_modules/grunt-contrib-watch/README.md new file mode 100644 index 000000000..fd7c6da51 --- /dev/null +++ b/node_modules/grunt-contrib-watch/README.md @@ -0,0 +1,429 @@ +# grunt-contrib-watch v0.5.3 [![Build Status](https://travis-ci.org/gruntjs/grunt-contrib-watch.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-watch) + +> Run predefined tasks whenever watched file patterns are added, changed or deleted. + + + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-contrib-watch --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-contrib-watch'); +``` + + + + +## Watch task +_Run this task with the `grunt watch` command._ + + +### Settings + +There are a number of options available. Please review the [minimatch options here](https://github.com/isaacs/minimatch#options). As well as some additional options as follows: + +#### files +Type: `String|Array` + +This defines what file patterns this task will watch. Can be a string or an array of files and/or minimatch patterns. + +#### tasks +Type: `String|Array` + +This defines which tasks to run when a watched file event occurs. + +#### options.spawn +Type: `Boolean` +Default: true + +Whether to spawn task runs in a child process. Setting this option to `false` speeds up the reaction time of the watch (usually 500ms faster for most) and allows subsequent task runs to share the same context. Not spawning task runs can make the watch more prone to failing so please use as needed. + +Example: +```js +watch: { + scripts: { + files: ['**/*.js'], + tasks: ['jshint'], + options: { + spawn: false, + }, + }, +}, +``` + +*For backwards compatibility the option `nospawn` is still available and will do the opposite of `spawn`.* + +#### options.interrupt +Type: `Boolean` +Default: false + +As files are modified this watch task will spawn tasks in child processes. The default behavior will only spawn a new child process per target when the previous process has finished. Set the `interrupt` option to true to terminate the previous process and spawn a new one upon later changes. + +Example: +```js +watch: { + scripts: { + files: '**/*.js', + tasks: ['jshint'], + options: { + interrupt: true, + }, + }, +}, +``` + +#### options.debounceDelay +Type: `Integer` +Default: 500 + +How long to wait before emitting events in succession for the same filepath and status. For example if your `Gruntfile.js` file was `changed`, a `changed` event will only fire again after the given milliseconds. + +Example: +```js +watch: { + scripts: { + files: '**/*.js', + tasks: ['jshint'], + options: { + debounceDelay: 250, + }, + }, +}, +``` + +#### options.interval +Type: `Integer` +Default: 100 + +The `interval` is passed to `fs.watchFile`. Since `interval` is only used by `fs.watchFile` and this watcher also uses `fs.watch`; it is recommended to ignore this option. *Default is 100ms*. + +#### options.event +Type: `String|Array` +Default: `'all'` + +Specify the type watch event that trigger the specified task. This option can be one or many of: `'all'`, `'changed'`, `'added'` and `'deleted'`. + +Example: +```js +watch: { + scripts: { + files: '**/*.js', + tasks: ['generateFileManifest'], + options: { + event: ['added', 'deleted'], + }, + }, +}, +``` + +#### options.forever +Type: `Boolean` +Default: true + +This is *only a task level option* and cannot be configured per target. By default the watch task will duck punch `grunt.fatal` and `grunt.warn` to try and prevent them from exiting the watch process. If you don't want `grunt.fatal` and `grunt.warn` to be overridden set the `forever` option to `false`. + +#### options.dateFormat +Type: `Function` + +This is *only a task level option* and cannot be configured per target. By default when the watch has finished running tasks it will display the message `Completed in 1.301s at Thu Jul 18 2013 14:58:21 GMT-0700 (PDT) - Waiting...`. You can override this message by supplying your own function: + +```js +watch: { + options: { + dateFormat: function(time) { + grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString()); + grunt.log.writeln('Waiting for more changes...'); + }, + }, + scripts: { + files: '**/*.js', + tasks: 'jshint', + }, +}, +``` + +#### options.atBegin +Type: `Boolean` +Default: false + +This option will trigger the run of each specified task at startup of the watcher. + +#### options.livereload +Type: `Boolean|Number|Object` +Default: false + +Set to `true` or set `livereload: 1337` to a port number to enable live reloading. Default and recommended port is `35729`. + +If enabled a live reload server will be started with the watch task per target. Then after the indicated tasks have ran, the live reload server will be triggered with the modified files. + +Example: +```js +watch: { + css: { + files: '**/*.sass', + tasks: ['sass'], + options: { + livereload: true, + }, + }, +}, +``` + +### Examples + +```js +// Simple config to run jshint any time a file is added, changed or deleted +grunt.initConfig({ + watch: { + files: ['**/*'], + tasks: ['jshint'], + }, +}); +``` + +```js +// Advanced config. Run specific tasks when specific files are added, changed or deleted. +grunt.initConfig({ + watch: { + gruntfile: { + files: 'Gruntfile.js', + tasks: ['jshint:gruntfile'], + }, + src: { + files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'], + tasks: ['default'], + }, + test: { + files: '<%= jshint.test.src %>', + tasks: ['jshint:test', 'qunit'], + }, + }, +}); +``` + +#### Using the `watch` event +This task will emit a `watch` event when watched files are modified. This is useful if you would like a simple notification when files are edited or if you're using this task in tandem with another task. Here is a simple example using the `watch` event: + +```js +grunt.initConfig({ + watch: { + scripts: { + files: ['lib/*.js'], + }, + }, +}); +grunt.event.on('watch', function(action, filepath, target) { + grunt.log.writeln(target + ': ' + filepath + ' has ' + action); +}); +``` + +**The `watch` event is not intended for replacing the standard Grunt API for configuring and running tasks. If you're trying to run tasks from within the `watch` event you're more than likely doing it wrong. Please read [configuring tasks](http://gruntjs.com/configuring-tasks).** + +##### Compiling Files As Needed +A very common request is to only compile files as needed. Here is an example that will only lint changed files with the `jshint` task: + +```js +grunt.initConfig({ + watch: { + scripts: { + files: ['lib/*.js'], + tasks: ['jshint'], + options: { + spawn: false, + }, + }, + }, + jshint: { + all: ['lib/*.js'], + }, +}); + +// on watch events configure jshint:all to only run on changed file +grunt.event.on('watch', function(action, filepath) { + grunt.config(['jshint', 'all'], filepath); +}); +``` + +If you need to dynamically modify your config, the `spawn` option must be disabled to keep the watch running under the same context. + +If you save multiple files simultaneously you may opt for a more robust method: + +```js +var changedFiles = Object.create(null); +var onChange = grunt.util._.debounce(function() { + grunt.config(['jshint', 'all'], Object.keys(changedFiles)); + changedFiles = Object.create(null); +}, 200); +grunt.event.on('watch', function(action, filepath) { + changedFiles[filepath] = action; + onChange(); +}); +``` + +#### Live Reloading +Live reloading is built into the watch task. Set the option `livereload` to `true` to enable on the default port `35729` or set to a custom port: `livereload: 1337`. + +The simplest way to add live reloading to all your watch targets is by setting `livereload` to `true` at the task level. This will run a single live reload server and trigger the live reload for all your watch targets: + +```js +grunt.initConfig({ + watch: { + options: { + livereload: true, + }, + css: { + files: ['public/scss/*.scss'], + tasks: ['compass'], + }, + }, +}); +``` + +You can also configure live reload for individual watch targets or run multiple live reload servers. Just be sure if you're starting multiple servers they operate on different ports: + +```js +grunt.initConfig({ + watch: { + css: { + files: ['public/scss/*.scss'], + tasks: ['compass'], + options: { + // Start a live reload server on the default port 35729 + livereload: true, + }, + }, + another: { + files: ['lib/*.js'], + tasks: ['anothertask'], + options: { + // Start another live reload server on port 1337 + livereload: 1337, + }, + }, + dont: { + files: ['other/stuff/*'], + tasks: ['dostuff'], + }, + }, +}); +``` + +##### Enabling Live Reload in Your HTML +Once you've started a live reload server you'll be able to access the live reload script. To enable live reload on your page, add a script tag before your closing `` tag pointing to the `livereload.js` script: + +```html + +``` + +Feel free to add this script to your template situation and toggle with some sort of `dev` flag. + +##### Using Live Reload with the Browser Extension +Instead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser. + +Once installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the ` +``` + +Feel free to add this script to your template situation and toggle with some sort of `dev` flag. + +### Using Live Reload with the Browser Extension +Instead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser. + +Once installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the ` +``` + +Using [`npm`](http://npmjs.org/): + +```bash +npm install lodash + +npm install -g lodash +npm link lodash +``` + +To avoid potential issues, update `npm` before installing Lo-Dash: + +```bash +npm install npm -g +``` + +In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/): + +```js +var _ = require('lodash'); + +// or as a drop-in replacement for Underscore +var _ = require('lodash/lodash.underscore'); +``` + +**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it. + +In [RingoJS v0.7.0-](http://ringojs.org/): + +```js +var _ = require('lodash')._; +``` + +In [Rhino](http://www.mozilla.org/rhino/): + +```js +load('lodash.js'); +``` + +In an AMD loader like [RequireJS](http://requirejs.org/): + +```js +require({ + 'paths': { + 'underscore': 'path/to/lodash' + } +}, +['underscore'], function(_) { + console.log(_.VERSION); +}); +``` + +## Release Notes + +### v1.0.1 + + * Add support for specifying source map URLs in `-p`/`--source-map` build options + * Ensured the second argument passed to `_.assign` is not treated as a `callback` + * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL` + * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed + * Made `_.defer` use `setImmediate`, in Node.js, when available + * Made `_.where` search arrays for values regardless of their index position + * Removed dead code from `_.template` + +The full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog). + +## BestieJS + +Lo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. + +## Author + +| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") | +|---| +| [John-David Dalton](http://allyoucanleet.com/) | + +## Contributors + +| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz "Follow @BlaineBublitz on Twitter") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") | +|---|---|---| +| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) | diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js new file mode 100644 index 000000000..37ebc920b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js @@ -0,0 +1,5152 @@ +/** + * @license + * Lo-Dash 1.0.1 (Custom Build) + * Build: `lodash -o ./dist/lodash.compat.js` + * Copyright 2012-2013 The Dojo Foundation + * Based on Underscore.js 1.4.4 + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. + * Available under MIT license + */ +;(function(window, undefined) { + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `module` */ + var freeModule = typeof module == 'object' && module && module.exports == freeExports && module; + + /** Detect free variable `global` and use it as `window` */ + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal) { + window = freeGlobal; + } + + /** Used for array and object method references */ + var arrayRef = [], + objectRef = {}; + + /** Used to generate unique IDs */ + var idCounter = 0; + + /** Used internally to indicate various things */ + var indicatorObject = objectRef; + + /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */ + var largeArraySize = 30; + + /** Used to restore the original `_` reference in `noConflict` */ + var oldDash = window._; + + /** Used to match HTML entities */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g; + + /** Used to match empty string literals in compiled template source */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match regexp flags from their coerced string values */ + var reFlags = /\w*$/; + + /** Used to detect if a method is native */ + var reNative = RegExp('^' + + (objectRef.valueOf + '') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + .replace(/valueOf|for [^\]]+/g, '.+?') + '$' + ); + + /** + * Used to match ES6 template delimiters + * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6 + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match "interpolate" template delimiters */ + var reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to ensure capturing order of template delimiters */ + var reNoMatch = /($^)/; + + /** Used to match HTML characters */ + var reUnescapedHtml = /[&<>"']/g; + + /** Used to match unescaped characters in compiled string literals */ + var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + + /** Used to fix the JScript [[DontEnum]] bug */ + var shadowed = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' + ]; + + /** Used to make template sourceURLs easier to identify */ + var templateCounter = 0; + + /** Native method shortcuts */ + var ceil = Math.ceil, + concat = arrayRef.concat, + floor = Math.floor, + getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, + hasOwnProperty = objectRef.hasOwnProperty, + push = arrayRef.push, + toString = objectRef.toString; + + /* Native method shortcuts for methods with the same name as other `lodash` methods */ + var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind, + nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, + nativeIsFinite = window.isFinite, + nativeIsNaN = window.isNaN, + nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys, + nativeMax = Math.max, + nativeMin = Math.min, + nativeRandom = Math.random; + + /** `Object#toString` result shortcuts */ + var argsClass = '[object Arguments]', + arrayClass = '[object Array]', + boolClass = '[object Boolean]', + dateClass = '[object Date]', + funcClass = '[object Function]', + numberClass = '[object Number]', + objectClass = '[object Object]', + regexpClass = '[object RegExp]', + stringClass = '[object String]'; + + /** Detect various environments */ + var isIeOpera = !!window.attachEvent, + isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera); + + /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */ + var isBindFast = nativeBind && !isV8; + + /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */ + var isKeysFast = nativeKeys && (isIeOpera || isV8); + + /** + * Detect the JScript [[DontEnum]] bug: + * + * In IE < 9 an objects own properties, shadowing non-enumerable ones, are + * made non-enumerable as well. + */ + var hasDontEnumBug; + + /** + * Detect if a `prototype` properties are enumerable by default: + * + * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + * (if the prototype or a property on the prototype has been set) + * incorrectly sets a function's `prototype` property [[Enumerable]] + * value to `true`. + */ + var hasEnumPrototype; + + /** Detect if own properties are iterated after inherited properties (IE < 9) */ + var iteratesOwnLast; + + /** + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * incorrectly: + * + * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` + * and `splice()` functions that fail to remove the last element, `value[0]`, + * of array-like objects even though the `length` property is set to `0`. + * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + */ + var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 }, + arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]); + + /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */ + var nonEnumArgs = true; + + (function() { + var props = []; + function ctor() { this.x = 1; } + ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var prop in new ctor) { props.push(prop); } + for (prop in arguments) { nonEnumArgs = !prop; } + + hasDontEnumBug = !/valueOf/.test(props); + hasEnumPrototype = ctor.propertyIsEnumerable('prototype'); + iteratesOwnLast = props[0] != 'x'; + }(1)); + + /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */ + var argsAreObjects = arguments.constructor == Object; + + /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */ + var noArgsClass = !isArguments(arguments); + + /** + * Detect lack of support for accessing string characters by index: + * + * IE < 8 can't access characters by index and IE 8 can only access + * characters by index on string literals. + */ + var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx'; + + /** + * Detect if a DOM node's [[Class]] is unresolvable (IE < 9) + * and that the JS engine won't error when attempting to coerce an object to + * a string without a `toString` function. + */ + try { + var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + ''); + } catch(e) { } + + /** Used to identify object classifications that `_.clone` supports */ + var cloneableClasses = {}; + cloneableClasses[funcClass] = false; + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[numberClass] = cloneableClasses[objectClass] = + cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + + /** Used to lookup a built-in constructor by [[Class]] */ + var ctorByClass = {}; + ctorByClass[arrayClass] = Array; + ctorByClass[boolClass] = Boolean; + ctorByClass[dateClass] = Date; + ctorByClass[objectClass] = Object; + ctorByClass[numberClass] = Number; + ctorByClass[regexpClass] = RegExp; + ctorByClass[stringClass] = String; + + /** Used to determine if values are of the language type Object */ + var objectTypes = { + 'boolean': false, + 'function': true, + 'object': true, + 'number': false, + 'string': false, + 'undefined': false + }; + + /** Used to escape characters for inclusion in compiled string literals */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object, that wraps the given `value`, to enable method + * chaining. + * + * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: + * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, + * and `unshift` + * + * The chainable wrapper functions are: + * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, + * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`, + * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`, + * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`, + * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, + * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip` + * + * The non-chainable wrapper functions are: + * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`, + * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, + * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, + * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, + * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`, + * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId` + * + * The wrapper functions `first` and `last` return wrapped values when `n` is + * passed, otherwise they return unwrapped values. + * + * @name _ + * @constructor + * @category Chaining + * @param {Mixed} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns a `lodash` instance. + */ + function lodash(value) { + // exit early if already wrapped, even if wrapped by a different `lodash` constructor + if (value && typeof value == 'object' && value.__wrapped__) { + return value; + } + // allow invoking `lodash` without the `new` operator + if (!(this instanceof lodash)) { + return new lodash(value); + } + this.__wrapped__ = value; + } + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in + * embedded Ruby (ERB). Change the following template settings to use alternative + * delimiters. + * + * @static + * @memberOf _ + * @type Object + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'escape': /<%-([\s\S]+?)%>/g, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'evaluate': /<%([\s\S]+?)%>/g, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type String + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type Object + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type Function + */ + '_': lodash + } + }; + + /*--------------------------------------------------------------------------*/ + + /** + * The template used to create iterator functions. + * + * @private + * @param {Obect} data The data object used to populate the text. + * @returns {String} Returns the interpolated text. + */ + var iteratorTemplate = function(obj) { + + var __p = 'var index, iterable = ' + + (obj.firstArg ) + + ', result = iterable;\nif (!iterable) return result;\n' + + (obj.top ) + + ';\n'; + if (obj.arrays) { + __p += 'var length = iterable.length; index = -1;\nif (' + + (obj.arrays ) + + ') { '; + if (obj.noCharByIndex) { + __p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } '; + } ; + __p += '\n while (++index < length) {\n ' + + (obj.loop ) + + '\n }\n}\nelse { '; + } else if (obj.nonEnumArgs) { + __p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' + + (obj.loop ) + + '\n }\n } else { '; + } ; + + if (obj.hasEnumPrototype) { + __p += '\n var skipProto = typeof iterable == \'function\';\n '; + } ; + + if (obj.isKeysFast && obj.useHas) { + __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n '; + if (obj.hasEnumPrototype) { + __p += 'if (!(skipProto && index == \'prototype\')) {\n '; + } ; + __p += + (obj.loop ) + + ''; + if (obj.hasEnumPrototype) { + __p += '}\n'; + } ; + __p += ' } '; + } else { + __p += '\n for (index in iterable) {'; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n if ('; + if (obj.hasEnumPrototype) { + __p += '!(skipProto && index == \'prototype\')'; + } if (obj.hasEnumPrototype && obj.useHas) { + __p += ' && '; + } if (obj.useHas) { + __p += 'hasOwnProperty.call(iterable, index)'; + } ; + __p += ') { '; + } ; + __p += + (obj.loop ) + + '; '; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n }'; + } ; + __p += '\n } '; + } ; + + if (obj.hasDontEnumBug) { + __p += '\n\n var ctor = iterable.constructor;\n '; + for (var k = 0; k < 7; k++) { + __p += '\n index = \'' + + (obj.shadowed[k] ) + + '\';\n if ('; + if (obj.shadowed[k] == 'constructor') { + __p += '!(ctor && ctor.prototype === iterable) && '; + } ; + __p += 'hasOwnProperty.call(iterable, index)) {\n ' + + (obj.loop ) + + '\n } '; + } ; + + } ; + + if (obj.arrays || obj.nonEnumArgs) { + __p += '\n}'; + } ; + __p += + (obj.bottom ) + + ';\nreturn result'; + + + return __p + }; + + /** Reusable iterator options for `assign` and `defaults` */ + var defaultsIteratorOptions = { + 'args': 'object, source, guard', + 'top': + 'var args = arguments,\n' + + ' argsIndex = 0,\n' + + " argsLength = typeof guard == 'number' ? 2 : args.length;\n" + + 'while (++argsIndex < argsLength) {\n' + + ' iterable = args[argsIndex];\n' + + ' if (iterable && objectTypes[typeof iterable]) {', + 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]", + 'bottom': ' }\n}' + }; + + /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */ + var eachIteratorOptions = { + 'args': 'collection, callback, thisArg', + 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)", + 'arrays': "typeof length == 'number'", + 'loop': 'if (callback(iterable[index], index, collection) === false) return result' + }; + + /** Reusable iterator options for `forIn` and `forOwn` */ + var forOwnIteratorOptions = { + 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top, + 'arrays': false + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function optimized to search large arrays for a given `value`, + * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`. + * + * @private + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=0] The index to search from. + * @param {Number} [largeSize=30] The length at which an array is considered large. + * @returns {Boolean} Returns `true`, if `value` is found, else `false`. + */ + function cachedContains(array, fromIndex, largeSize) { + fromIndex || (fromIndex = 0); + + var length = array.length, + isLarge = (length - fromIndex) >= (largeSize || largeArraySize); + + if (isLarge) { + var cache = {}, + index = fromIndex - 1; + + while (++index < length) { + // manually coerce `value` to a string because `hasOwnProperty`, in some + // older versions of Firefox, coerces objects incorrectly + var key = array[index] + ''; + (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]); + } + } + return function(value) { + if (isLarge) { + var key = value + ''; + return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1; + } + return indexOf(array, value, fromIndex) > -1; + } + } + + /** + * Used by `_.max` and `_.min` as the default `callback` when a given + * `collection` is a string value. + * + * @private + * @param {String} value The character to inspect. + * @returns {Number} Returns the code unit of given character. + */ + function charAtCallback(value) { + return value.charCodeAt(0); + } + + /** + * Used by `sortBy` to compare transformed `collection` values, stable sorting + * them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {Number} Returns the sort order indicator of `1` or `-1`. + */ + function compareAscending(a, b) { + var ai = a.index, + bi = b.index; + + a = a.criteria; + b = b.criteria; + + // ensure a stable sort in V8 and other engines + // http://code.google.com/p/v8/issues/detail?id=90 + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return ai < bi ? -1 : 1; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` binding + * of `thisArg` and prepends any `partialArgs` to the arguments passed to the + * bound function. + * + * @private + * @param {Function|String} func The function to bind or the method name. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Array} partialArgs An array of arguments to be partially applied. + * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right. + * @returns {Function} Returns the new bound function. + */ + function createBound(func, thisArg, partialArgs, rightIndicator) { + var isFunc = isFunction(func), + isPartial = !partialArgs, + key = thisArg; + + // juggle arguments + if (isPartial) { + partialArgs = thisArg; + } + if (!isFunc) { + thisArg = func; + } + + function bound() { + // `Function#bind` spec + // http://es5.github.com/#x15.3.4.5 + var args = arguments, + thisBinding = isPartial ? this : thisArg; + + if (!isFunc) { + func = thisArg[key]; + } + if (partialArgs.length) { + args = args.length + ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args)) + : partialArgs; + } + if (this instanceof bound) { + // ensure `new bound` is an instance of `bound` and `func` + noop.prototype = func.prototype; + thisBinding = new noop; + noop.prototype = null; + + // mimic the constructor's `return` behavior + // http://es5.github.com/#x13.2.2 + var result = func.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + } + return func.apply(thisBinding, args); + } + return bound; + } + + /** + * Produces a callback bound to an optional `thisArg`. If `func` is a property + * name, the created callback will return the property value for a given element. + * If `func` is an object, the created callback will return `true` for elements + * that contain the equivalent object properties, otherwise it will return `false`. + * + * @private + * @param {Mixed} [func=identity] The value to convert to a callback. + * @param {Mixed} [thisArg] The `this` binding of the created callback. + * @param {Number} [argCount=3] The number of arguments the callback accepts. + * @returns {Function} Returns a callback function. + */ + function createCallback(func, thisArg, argCount) { + if (func == null) { + return identity; + } + var type = typeof func; + if (type != 'function') { + if (type != 'object') { + return function(object) { + return object[func]; + }; + } + var props = keys(func); + return function(object) { + var length = props.length, + result = false; + while (length--) { + if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) { + break; + } + } + return result; + }; + } + if (typeof thisArg != 'undefined') { + if (argCount === 1) { + return function(value) { + return func.call(thisArg, value); + }; + } + if (argCount === 2) { + return function(a, b) { + return func.call(thisArg, a, b); + }; + } + if (argCount === 4) { + return function(accumulator, value, index, object) { + return func.call(thisArg, accumulator, value, index, object); + }; + } + return function(value, index, object) { + return func.call(thisArg, value, index, object); + }; + } + return func; + } + + /** + * Creates compiled iteration functions. + * + * @private + * @param {Object} [options1, options2, ...] The compile options object(s). + * arrays - A string of code to determine if the iterable is an array or array-like. + * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop. + * args - A string of comma separated arguments the iteration function will accept. + * top - A string of code to execute before the iteration branches. + * loop - A string of code to execute in the object loop. + * bottom - A string of code to execute after the iteration branches. + * + * @returns {Function} Returns the compiled function. + */ + function createIterator() { + var data = { + // support properties + 'hasDontEnumBug': hasDontEnumBug, + 'hasEnumPrototype': hasEnumPrototype, + 'isKeysFast': isKeysFast, + 'nonEnumArgs': nonEnumArgs, + 'noCharByIndex': noCharByIndex, + 'shadowed': shadowed, + + // iterator options + 'arrays': 'isArray(iterable)', + 'bottom': '', + 'loop': '', + 'top': '', + 'useHas': true + }; + + // merge options into a template data object + for (var object, index = 0; object = arguments[index]; index++) { + for (var key in object) { + data[key] = object[key]; + } + } + var args = data.args; + data.firstArg = /^[^,]+/.exec(args)[0]; + + // create the function factory + var factory = Function( + 'createCallback, hasOwnProperty, isArguments, isArray, isString, ' + + 'objectTypes, nativeKeys', + 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' + ); + // return the compiled function + return factory( + createCallback, hasOwnProperty, isArguments, isArray, isString, + objectTypes, nativeKeys + ); + } + + /** + * A function compiled to iterate `arguments` objects, arrays, objects, and + * strings consistenly across environments, executing the `callback` for each + * element in the `collection`. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). Callbacks may exit + * iteration early by explicitly returning `false`. + * + * @private + * @type Function + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + */ + var each = createIterator(eachIteratorOptions); + + /** + * Used by `template` to escape characters for inclusion in compiled + * string literals. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeStringChar(match) { + return '\\' + stringEscapes[match]; + } + + /** + * Used by `escape` to convert characters to HTML entities. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } + + /** + * Checks if `value` is a DOM node in IE < 9. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`. + */ + function isNode(value) { + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + } + + /** + * A no-operation function. + * + * @private + */ + function noop() { + // no operation performed + } + + /** + * Slices the `collection` from the `start` index up to, but not including, + * the `end` index. + * + * Note: This function is used, instead of `Array#slice`, to support node lists + * in IE < 9 and to ensure dense arrays are returned. + * + * @private + * @param {Array|Object|String} collection The collection to slice. + * @param {Number} start The start index. + * @param {Number} end The end index. + * @returns {Array} Returns the new array. + */ + function slice(array, start, end) { + start || (start = 0); + if (typeof end == 'undefined') { + end = array ? array.length : 0; + } + var index = -1, + length = end - start || 0, + result = Array(length < 0 ? 0 : length); + + while (++index < length) { + result[index] = array[start + index]; + } + return result; + } + + /** + * Used by `unescape` to convert HTML entities to characters. + * + * @private + * @param {String} match The matched character to unescape. + * @returns {String} Returns the unescaped character. + */ + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Checks if `value` is an `arguments` object. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`. + * @example + * + * (function() { return _.isArguments(arguments); })(1, 2, 3); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + function isArguments(value) { + return toString.call(value) == argsClass; + } + // fallback for browsers that can't detect `arguments` objects by [[Class]] + if (noArgsClass) { + isArguments = function(value) { + return value ? hasOwnProperty.call(value, 'callee') : false; + }; + } + + /** + * Iterates over `object`'s own and inherited enumerable properties, executing + * the `callback` for each property. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, key, object). Callbacks may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * function Dog(name) { + * this.name = name; + * } + * + * Dog.prototype.bark = function() { + * alert('Woof, woof!'); + * }; + * + * _.forIn(new Dog('Dagny'), function(value, key) { + * alert(key); + * }); + * // => alerts 'name' and 'bark' (order is not guaranteed) + */ + var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, { + 'useHas': false + }); + + /** + * Iterates over an object's own enumerable properties, executing the `callback` + * for each property. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, key, object). Callbacks may exit iteration early by explicitly + * returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * alert(key); + * }); + * // => alerts '0', '1', and 'length' (order is not guaranteed) + */ + var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions); + + /** + * Checks if `value` is an array. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`. + * @example + * + * (function() { return _.isArray(arguments); })(); + * // => false + * + * _.isArray([1, 2, 3]); + * // => true + */ + var isArray = nativeIsArray || function(value) { + // `instanceof` may cause a memory leak in IE 7 if `value` is a host object + // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak + return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass; + }; + + /** + * Creates an array composed of the own enumerable property names of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + * @example + * + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (order is not guaranteed) + */ + var keys = !nativeKeys ? shimKeys : function(object) { + if (!isObject(object)) { + return []; + } + if ((hasEnumPrototype && typeof object == 'function') || + (nonEnumArgs && object.length && isArguments(object))) { + return shimKeys(object); + } + return nativeKeys(object); + }; + + /** + * A fallback implementation of `isPlainObject` that checks if a given `value` + * is an object created by the `Object` constructor, assuming objects created + * by the `Object` constructor have no inherited enumerable properties and that + * there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + */ + function shimIsPlainObject(value) { + // avoid non-objects and false positives for `arguments` objects + var result = false; + if (!(value && typeof value == 'object') || isArguments(value)) { + return result; + } + // check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) { + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + if (iteratesOwnLast) { + forIn(value, function(value, key, object) { + result = !hasOwnProperty.call(object, key); + return false; + }); + return result === false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + forIn(value, function(value, key) { + result = key; + }); + return result === false || hasOwnProperty.call(value, result); + } + return result; + } + + /** + * A fallback implementation of `Object.keys` that produces an array of the + * given object's own enumerable property names. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + */ + function shimKeys(object) { + var result = []; + forOwn(object, function(value, key) { + result.push(key); + }); + return result; + } + + /** + * Used to convert characters to HTML entities: + * + * Though the `>` character is escaped for symmetry, characters like `>` and `/` + * don't require escaping in HTML and have no special meaning unless they're part + * of a tag or an unquoted attribute value. + * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to convert HTML entities to characters */ + var htmlUnescapes = invert(htmlEscapes); + + /*--------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources will overwrite propery assignments of previous + * sources. If a `callback` function is passed, it will be executed to produce + * the assigned values. The `callback` is bound to `thisArg` and invoked with + * two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @type Function + * @alias extend + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize assigning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the destination object. + * @example + * + * _.assign({ 'name': 'moe' }, { 'age': 40 }); + * // => { 'name': 'moe', 'age': 40 } + * + * var defaults = _.partialRight(_.assign, function(a, b) { + * return typeof a == 'undefined' ? b : a; + * }); + * + * var food = { 'name': 'apple' }; + * defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var assign = createIterator(defaultsIteratorOptions, { + 'top': + defaultsIteratorOptions.top.replace(';', + ';\n' + + "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" + + ' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' + + "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" + + ' callback = args[--argsLength];\n' + + '}' + ), + 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]' + }); + + /** + * Creates a clone of `value`. If `deep` is `true`, nested objects will also + * be cloned, otherwise they will be assigned by reference. If a `callback` + * function is passed, it will be executed to produce the cloned values. If + * `callback` returns `undefined`, cloning will be handled by the method instead. + * The `callback` is bound to `thisArg` and invoked with one argument; (value). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to clone. + * @param {Boolean} [deep=false] A flag to indicate a deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts. + * @returns {Mixed} Returns the cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var shallow = _.clone(stooges); + * shallow[0] === stooges[0]; + * // => true + * + * var deep = _.clone(stooges, true); + * deep[0] === stooges[0]; + * // => false + * + * _.mixin({ + * 'clone': _.partialRight(_.clone, function(value) { + * return _.isElement(value) ? value.cloneNode(false) : undefined; + * }) + * }); + * + * var clone = _.clone(document.body); + * clone.childNodes.length; + * // => 0 + */ + function clone(value, deep, callback, thisArg, stackA, stackB) { + var result = value; + + // allows working with "Collections" methods without using their `callback` + // argument, `index|key`, for this method's `callback` + if (typeof deep == 'function') { + thisArg = callback; + callback = deep; + deep = false; + } + if (typeof callback == 'function') { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1); + result = callback(result); + + var done = typeof result != 'undefined'; + if (!done) { + result = value; + } + } + // inspect [[Class]] + var isObj = isObject(result); + if (isObj) { + var className = toString.call(result); + if (!cloneableClasses[className] || (noNodeClass && isNode(result))) { + return result; + } + var isArr = isArray(result); + } + // shallow clone + if (!isObj || !deep) { + return isObj && !done + ? (isArr ? slice(result) : assign({}, result)) + : result; + } + var ctor = ctorByClass[className]; + switch (className) { + case boolClass: + case dateClass: + return done ? result : new ctor(+result); + + case numberClass: + case stringClass: + return done ? result : new ctor(result); + + case regexpClass: + return done ? result : ctor(result.source, reFlags.exec(result)); + } + // check for circular references and return corresponding clone + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // init cloned object + if (!done) { + result = isArr ? ctor(result.length) : {}; + + // add array properties assigned by `RegExp#exec` + if (isArr) { + if (hasOwnProperty.call(value, 'index')) { + result.index = value.index; + } + if (hasOwnProperty.call(value, 'input')) { + result.input = value.input; + } + } + } + // add the source value to the stack of traversed objects + // and associate it with its clone + stackA.push(value); + stackB.push(result); + + // recursively populate clone (susceptible to call stack limits) + (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) { + result[key] = clone(objValue, deep, callback, undefined, stackA, stackB); + }); + + return result; + } + + /** + * Creates a deep clone of `value`. If a `callback` function is passed, it will + * be executed to produce the cloned values. If `callback` returns the value it + * was passed, cloning will be handled by the method instead. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * Note: This function is loosely based on the structured clone algorithm. Functions + * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and + * objects created by constructors other than `Object` are cloned to plain `Object` objects. + * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the deep cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var deep = _.cloneDeep(stooges); + * deep[0] === stooges[0]; + * // => false + * + * var view = { + * 'label': 'docs', + * 'node': element + * }; + * + * var clone = _.cloneDeep(view, function(value) { + * return _.isElement(value) ? value.cloneNode(true) : value; + * }); + * + * clone.node == view.node; + * // => false + */ + function cloneDeep(value, callback, thisArg) { + return clone(value, true, callback, thisArg); + } + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property will be ignored. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param- {Object} [guard] Internally used to allow working with `_.reduce` + * without using its callback's `key` and `object` arguments as sources. + * @returns {Object} Returns the destination object. + * @example + * + * var food = { 'name': 'apple' }; + * _.defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var defaults = createIterator(defaultsIteratorOptions); + + /** + * Creates a sorted array of all enumerable properties, own and inherited, + * of `object` that have function values. + * + * @static + * @memberOf _ + * @alias methods + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names that have function values. + * @example + * + * _.functions(_); + * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + */ + function functions(object) { + var result = []; + forIn(object, function(value, key) { + if (isFunction(value)) { + result.push(key); + } + }); + return result.sort(); + } + + /** + * Checks if the specified object `property` exists and is a direct property, + * instead of an inherited property. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to check. + * @param {String} property The property to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + * @example + * + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); + * // => true + */ + function has(object, property) { + return object ? hasOwnProperty.call(object, property) : false; + } + + /** + * Creates an object composed of the inverted keys and values of the given `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to invert. + * @returns {Object} Returns the created inverted object. + * @example + * + * _.invert({ 'first': 'moe', 'second': 'larry' }); + * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed) + */ + function invert(object) { + var index = -1, + props = keys(object), + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + result[object[key]] = key; + } + return result; + } + + /** + * Checks if `value` is a boolean value. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`. + * @example + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || toString.call(value) == boolClass; + } + + /** + * Checks if `value` is a date. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + */ + function isDate(value) { + return value instanceof Date || toString.call(value) == dateClass; + } + + /** + * Checks if `value` is a DOM element. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + */ + function isElement(value) { + return value ? value.nodeType === 1 : false; + } + + /** + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object|String} value The value to inspect. + * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`. + * @example + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({}); + * // => true + * + * _.isEmpty(''); + * // => true + */ + function isEmpty(value) { + var result = true; + if (!value) { + return result; + } + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + className == argsClass || (noArgsClass && isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + return !length; + } + forOwn(value, function() { + return (result = false); + }); + return result; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent to each other. If `callback` is passed, it will be executed to + * compare values. If `callback` returns `undefined`, comparisons will be handled + * by the method instead. The `callback` is bound to `thisArg` and invoked with + * two arguments; (a, b). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} a The value to compare. + * @param {Mixed} b The other value to compare. + * @param {Function} [callback] The function to customize comparing values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [stackA=[]] Internally used track traversed `a` objects. + * @param- {Object} [stackB=[]] Internally used track traversed `b` objects. + * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`. + * @example + * + * var moe = { 'name': 'moe', 'age': 40 }; + * var copy = { 'name': 'moe', 'age': 40 }; + * + * moe == copy; + * // => false + * + * _.isEqual(moe, copy); + * // => true + * + * var words = ['hello', 'goodbye']; + * var otherWords = ['hi', 'goodbye']; + * + * _.isEqual(words, otherWords, function(a, b) { + * var reGreet = /^(?:hello|hi)$/i, + * aGreet = _.isString(a) && reGreet.test(a), + * bGreet = _.isString(b) && reGreet.test(b); + * + * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; + * }); + * // => true + */ + function isEqual(a, b, callback, thisArg, stackA, stackB) { + // used to indicate that when comparing objects, `a` has at least the properties of `b` + var whereIndicator = callback === indicatorObject; + if (callback && !whereIndicator) { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2); + var result = callback(a, b); + if (typeof result != 'undefined') { + return !!result; + } + } + // exit early for identical values + if (a === b) { + // treat `+0` vs. `-0` as not equal + return a !== 0 || (1 / a == 1 / b); + } + var type = typeof a, + otherType = typeof b; + + // exit early for unlike primitive values + if (a === a && + (!a || (type != 'function' && type != 'object')) && + (!b || (otherType != 'function' && otherType != 'object'))) { + return false; + } + // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior + // http://es5.github.com/#x15.3.4.4 + if (a == null || b == null) { + return a === b; + } + // compare [[Class]] names + var className = toString.call(a), + otherClass = toString.call(b); + + if (className == argsClass) { + className = objectClass; + } + if (otherClass == argsClass) { + otherClass = objectClass; + } + if (className != otherClass) { + return false; + } + switch (className) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal + return +a == +b; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return a != +a + ? b != +b + // but treat `+0` vs. `-0` as not equal + : (a == 0 ? (1 / a == 1 / b) : a == +b); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.com/#x15.10.6.4) + // treat string primitives and their corresponding object instances as equal + return a == b + ''; + } + var isArr = className == arrayClass; + if (!isArr) { + // unwrap any `lodash` wrapped values + if (a.__wrapped__ || b.__wrapped__) { + return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB); + } + // exit for functions and DOM nodes + if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) { + return false; + } + // in older versions of Opera, `arguments` objects have `Array` constructors + var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor, + ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor; + + // non `Object` object instances with different constructors are not equal + if (ctorA != ctorB && !( + isFunction(ctorA) && ctorA instanceof ctorA && + isFunction(ctorB) && ctorB instanceof ctorB + )) { + return false; + } + } + // assume cyclic structures are equal + // the algorithm for detecting cyclic structures is adapted from ES 5.1 + // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3) + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == a) { + return stackB[length] == b; + } + } + var size = 0; + result = true; + + // add `a` and `b` to the stack of traversed objects + stackA.push(a); + stackB.push(b); + + // recursively compare objects and arrays (susceptible to call stack limits) + if (isArr) { + length = a.length; + size = b.length; + + // compare lengths to determine if a deep comparison is necessary + result = size == a.length; + if (!result && !whereIndicator) { + return result; + } + // deep compare the contents, ignoring non-numeric properties + while (size--) { + var index = length, + value = b[size]; + + if (whereIndicator) { + while (index--) { + if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) { + break; + } + } + } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) { + break; + } + } + return result; + } + // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` + // which, in this case, is more costly + forIn(b, function(value, key, b) { + if (hasOwnProperty.call(b, key)) { + // count the number of properties. + size++; + // deep compare each property value. + return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB)); + } + }); + + if (result && !whereIndicator) { + // ensure both objects have the same number of properties + forIn(a, function(value, key, a) { + if (hasOwnProperty.call(a, key)) { + // `size` will be `-1` if `a` has more properties than `b` + return (result = --size > -1); + } + }); + } + return result; + } + + /** + * Checks if `value` is, or can be coerced to, a finite number. + * + * Note: This is not the same as native `isFinite`, which will return true for + * booleans and empty strings. See http://es5.github.com/#x15.1.2.5. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`. + * @example + * + * _.isFinite(-101); + * // => true + * + * _.isFinite('10'); + * // => true + * + * _.isFinite(true); + * // => false + * + * _.isFinite(''); + * // => false + * + * _.isFinite(Infinity); + * // => false + */ + function isFinite(value) { + return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + } + + /** + * Checks if `value` is a function. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + */ + function isFunction(value) { + return typeof value == 'function'; + } + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return value instanceof Function || toString.call(value) == funcClass; + }; + } + + /** + * Checks if `value` is the language type of Object. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ + function isObject(value) { + // check if the value is the ECMAScript language type of Object + // http://es5.github.com/#x8 + // and avoid a V8 bug + // http://code.google.com/p/v8/issues/detail?id=2291 + return value ? objectTypes[typeof value] : false; + } + + /** + * Checks if `value` is `NaN`. + * + * Note: This is not the same as native `isNaN`, which will return `true` for + * `undefined` and other values. See http://es5.github.com/#x15.1.2.4. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // `NaN` as a primitive is the only value that is not equal to itself + // (perform the [[Class]] check first to avoid errors with some host objects in IE) + return isNumber(value) && value != +value + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(undefined); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is a number. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`. + * @example + * + * _.isNumber(8.4 * 5); + * // => true + */ + function isNumber(value) { + return typeof value == 'number' || toString.call(value) == numberClass; + } + + /** + * Checks if a given `value` is an object created by the `Object` constructor. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + * @example + * + * function Stooge(name, age) { + * this.name = name; + * this.age = age; + * } + * + * _.isPlainObject(new Stooge('moe', 40)); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'name': 'moe', 'age': 40 }); + * // => true + */ + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && typeof value == 'object')) { + return false; + } + var valueOf = value.valueOf, + objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value)) + : shimIsPlainObject(value); + }; + + /** + * Checks if `value` is a regular expression. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`. + * @example + * + * _.isRegExp(/moe/); + * // => true + */ + function isRegExp(value) { + return value instanceof RegExp || toString.call(value) == regexpClass; + } + + /** + * Checks if `value` is a string. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`. + * @example + * + * _.isString('moe'); + * // => true + */ + function isString(value) { + return typeof value == 'string' || toString.call(value) == stringClass; + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + */ + function isUndefined(value) { + return typeof value == 'undefined'; + } + + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined`, into the destination object. Subsequent sources + * will overwrite propery assignments of previous sources. If a `callback` function + * is passed, it will be executed to produce the merged values of the destination + * and source properties. If `callback` returns `undefined`, merging will be + * handled by the method instead. The `callback` is bound to `thisArg` and + * invoked with two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize merging properties. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [deepIndicator] Internally used to indicate that `stackA` + * and `stackB` are arrays of traversed objects instead of source objects. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate values with their + * source counterparts. + * @returns {Object} Returns the destination object. + * @example + * + * var names = { + * 'stooges': [ + * { 'name': 'moe' }, + * { 'name': 'larry' } + * ] + * }; + * + * var ages = { + * 'stooges': [ + * { 'age': 40 }, + * { 'age': 50 } + * ] + * }; + * + * _.merge(names, ages); + * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] } + * + * var food = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var otherFood = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(food, otherFood, function(a, b) { + * return _.isArray(a) ? a.concat(b) : undefined; + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + */ + function merge(object, source, deepIndicator) { + var args = arguments, + index = 0, + length = 2; + + if (!isObject(object)) { + return object; + } + if (deepIndicator === indicatorObject) { + var callback = args[3], + stackA = args[4], + stackB = args[5]; + } else { + stackA = []; + stackB = []; + + // allows working with `_.reduce` and `_.reduceRight` without + // using their `callback` arguments, `index|key` and `collection` + if (typeof deepIndicator != 'number') { + length = args.length; + } + if (length > 3 && typeof args[length - 2] == 'function') { + callback = createCallback(args[--length - 1], args[length--], 2); + } else if (length > 2 && typeof args[length - 1] == 'function') { + callback = args[--length]; + } + } + while (++index < length) { + (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) { + var found, + isArr, + result = source, + value = object[key]; + + if (source && ((isArr = isArray(source)) || isPlainObject(source))) { + // avoid merging previously merged cyclic sources + var stackLength = stackA.length; + while (stackLength--) { + if ((found = stackA[stackLength] == source)) { + value = stackB[stackLength]; + break; + } + } + if (!found) { + value = isArr + ? (isArray(value) ? value : []) + : (isPlainObject(value) ? value : {}); + + if (callback) { + result = callback(value, source); + if (typeof result != 'undefined') { + value = result; + } + } + // add `source` and associated `value` to the stack of traversed objects + stackA.push(source); + stackB.push(value); + + // recursively merge objects and arrays (susceptible to call stack limits) + if (!callback) { + value = merge(value, source, indicatorObject, callback, stackA, stackB); + } + } + } + else { + if (callback) { + result = callback(value, source); + if (typeof result == 'undefined') { + result = source; + } + } + if (typeof result != 'undefined') { + value = result; + } + } + object[key] = value; + }); + } + return object; + } + + /** + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a `callback` function is passed, it will be executed + * for each property in the `object`, omitting the properties `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit + * or the function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. + * @example + * + * _.omit({ 'name': 'moe', 'age': 40 }, 'age'); + * // => { 'name': 'moe' } + * + * _.omit({ 'name': 'moe', 'age': 40 }, function(value) { + * return typeof value == 'number'; + * }); + * // => { 'name': 'moe' } + */ + function omit(object, callback, thisArg) { + var isFunc = typeof callback == 'function', + result = {}; + + if (isFunc) { + callback = createCallback(callback, thisArg); + } else { + var props = concat.apply(arrayRef, arguments); + } + forIn(object, function(value, key, object) { + if (isFunc + ? !callback(value, key, object) + : indexOf(props, key, 1) < 0 + ) { + result[key] = value; + } + }); + return result; + } + + /** + * Creates a two dimensional array of the given object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. + * @example + * + * _.pairs({ 'moe': 30, 'larry': 40 }); + * // => [['moe', 30], ['larry', 40]] (order is not guaranteed) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of property + * names. If `callback` is passed, it will be executed for each property in the + * `object`, picking the properties `callback` returns truthy for. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called + * per iteration or properties to pick, either as individual arguments or arrays. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name'); + * // => { 'name': 'moe' } + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'moe' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = 0, + props = concat.apply(arrayRef, arguments), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = createCallback(callback, thisArg); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * Creates an array composed of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property values. + * @example + * + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] + */ + function values(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array of elements from the specified indexes, or keys, of the + * `collection`. Indexes may be specified as individual arguments or as arrays + * of indexes. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Array|Number|String} [index1, index2, ...] The indexes of + * `collection` to retrieve, either as individual arguments or arrays. + * @returns {Array} Returns a new array of elements corresponding to the + * provided indexes. + * @example + * + * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); + * // => ['a', 'c', 'e'] + * + * _.at(['moe', 'larry', 'curly'], 0, 2); + * // => ['moe', 'curly'] + */ + function at(collection) { + var index = -1, + props = concat.apply(arrayRef, slice(arguments, 1)), + length = props.length, + result = Array(length); + + if (noCharByIndex && isString(collection)) { + collection = collection.split(''); + } + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + + /** + * Checks if a given `target` element is present in a `collection` using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @alias include + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Mixed} target The value to check for. + * @param {Number} [fromIndex=0] The index to search from. + * @returns {Boolean} Returns `true` if the `target` element is found, else `false`. + * @example + * + * _.contains([1, 2, 3], 1); + * // => true + * + * _.contains([1, 2, 3], 1, 2); + * // => false + * + * _.contains({ 'name': 'moe', 'age': 40 }, 'moe'); + * // => true + * + * _.contains('curly', 'ur'); + * // => true + */ + function contains(collection, target, fromIndex) { + var index = -1, + length = collection ? collection.length : 0, + result = false; + + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; + if (typeof length == 'number') { + result = (isString(collection) + ? collection.indexOf(target, fromIndex) + : indexOf(collection, target, fromIndex) + ) > -1; + } else { + each(collection, function(value) { + if (++index >= fromIndex) { + return !(result = value === target); + } + }); + } + return result; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the given `callback`. The corresponding value of each key + * is the number of times the key was returned by the `callback`. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': 1, '6': 2 } + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + function countBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); + }); + return result; + } + + /** + * Checks if the `callback` returns a truthy value for **all** elements of a + * `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias all + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if all elements pass the callback check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.every(stooges, 'age'); + * // => true + * + * // using "_.where" callback shorthand + * _.every(stooges, { 'age': 50 }); + * // => false + */ + function every(collection, callback, thisArg) { + var result = true; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (!(result = !!callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return (result = !!callback(value, index, collection)); + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * the `callback` returns truthy for. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias select + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that passed the callback check. + * @example + * + * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [2, 4, 6] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.filter(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + * + * // using "_.where" callback shorthand + * _.filter(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + */ + function filter(collection, callback, thisArg) { + var result = []; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (callback(value, index, collection)) { + result.push(value); + } + } + } else { + each(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result.push(value); + } + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning the first that the `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias detect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the element that passed the callback check, + * else `undefined`. + * @example + * + * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => 2 + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'banana', 'organic': true, 'type': 'fruit' }, + * { 'name': 'beet', 'organic': false, 'type': 'vegetable' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * var veggie = _.find(food, { 'type': 'vegetable' }); + * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' } + * + * // using "_.pluck" callback shorthand + * var healthy = _.find(food, 'organic'); + * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' } + */ + function find(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; + } + + /** + * Iterates over a `collection`, executing the `callback` for each element in + * the `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). Callbacks may exit iteration early + * by explicitly returning `false`. + * + * @static + * @memberOf _ + * @alias each + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + * @example + * + * _([1, 2, 3]).forEach(alert).join(','); + * // => alerts each number and returns '1,2,3' + * + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert); + * // => alerts each number value (order is not guaranteed) + */ + function forEach(collection, callback, thisArg) { + if (callback && typeof thisArg == 'undefined' && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (callback(collection[index], index, collection) === false) { + break; + } + } + } else { + each(collection, callback, thisArg); + } + return collection; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the `callback`. The corresponding value of each key is + * an array of elements passed to `callback` that returned the key. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false` + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * // using "_.pluck" callback shorthand + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + function groupBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); + }); + return result; + } + + /** + * Invokes the method named by `methodName` on each element in the `collection`, + * returning an array of the results of each invoked method. Additional arguments + * will be passed to each invoked method. If `methodName` is a function, it will + * be invoked for, and `this` bound to, each element in the `collection`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} Returns a new array of the results of each invoked method. + * @example + * + * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invoke([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + function invoke(collection, methodName) { + var args = slice(arguments, 2), + index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); + }); + return result; + } + + /** + * Creates an array of values by running each element in the `collection` + * through the `callback`. The `callback` is bound to `thisArg` and invoked with + * three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias collect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of the results of each `callback` execution. + * @example + * + * _.map([1, 2, 3], function(num) { return num * 3; }); + * // => [3, 6, 9] + * + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * // => [3, 6, 9] (order is not guaranteed) + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.map(stooges, 'name'); + * // => ['moe', 'larry'] + */ + function map(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + if (isArray(collection)) { + while (++index < length) { + result[index] = callback(collection[index], index, collection); + } + } else { + each(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); + } + return result; + } + + /** + * Retrieves the maximum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.max(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'larry', 'age': 50 }; + * + * // using "_.pluck" callback shorthand + * _.max(stooges, 'age'); + * // => { 'name': 'larry', 'age': 50 }; + */ + function max(collection, callback, thisArg) { + var computed = -Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value > result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current > computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the minimum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.min(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'moe', 'age': 40 }; + * + * // using "_.pluck" callback shorthand + * _.min(stooges, 'age'); + * // => { 'name': 'moe', 'age': 40 }; + */ + function min(collection, callback, thisArg) { + var computed = Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value < result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current < computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the value of a specified property from all elements in the `collection`. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {String} property The property to pluck. + * @returns {Array} Returns a new array of property values. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.pluck(stooges, 'name'); + * // => ['moe', 'larry'] + */ + var pluck = map; + + /** + * Reduces a `collection` to a value that is the accumulated result of running + * each element in the `collection` through the `callback`, where each successive + * `callback` execution consumes the return value of the previous execution. + * If `accumulator` is not passed, the first element of the `collection` will be + * used as the initial `accumulator` value. The `callback` is bound to `thisArg` + * and invoked with four arguments; (accumulator, value, index|key, collection). + * + * @static + * @memberOf _ + * @alias foldl, inject + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var sum = _.reduce([1, 2, 3], function(sum, num) { + * return sum + num; + * }); + * // => 6 + * + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * return result; + * }, {}); + * // => { 'a': 3, 'b': 6, 'c': 9 } + */ + function reduce(collection, callback, accumulator, thisArg) { + var noaccum = arguments.length < 3; + callback = createCallback(callback, thisArg, 4); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + if (noaccum) { + accumulator = collection[++index]; + } + while (++index < length) { + accumulator = callback(accumulator, collection[index], index, collection); + } + } else { + each(collection, function(value, index, collection) { + accumulator = noaccum + ? (noaccum = false, value) + : callback(accumulator, value, index, collection) + }); + } + return accumulator; + } + + /** + * This method is similar to `_.reduce`, except that it iterates over a + * `collection` from right to left. + * + * @static + * @memberOf _ + * @alias foldr + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var list = [[0, 1], [2, 3], [4, 5]]; + * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, callback, accumulator, thisArg) { + var iterable = collection, + length = collection ? collection.length : 0, + noaccum = arguments.length < 3; + + if (typeof length != 'number') { + var props = keys(collection); + length = props.length; + } else if (noCharByIndex && isString(collection)) { + iterable = collection.split(''); + } + callback = createCallback(callback, thisArg, 4); + forEach(collection, function(value, index, collection) { + index = props ? props[--length] : --length; + accumulator = noaccum + ? (noaccum = false, iterable[index]) + : callback(accumulator, iterable[index], index, collection); + }); + return accumulator; + } + + /** + * The opposite of `_.filter`, this method returns the elements of a + * `collection` that `callback` does **not** return truthy for. + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that did **not** pass the + * callback check. + * @example + * + * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [1, 3, 5] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.reject(food, 'organic'); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + * + * // using "_.where" callback shorthand + * _.reject(food, { 'type': 'fruit' }); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + */ + function reject(collection, callback, thisArg) { + callback = createCallback(callback, thisArg); + return filter(collection, function(value, index, collection) { + return !callback(value, index, collection); + }); + } + + /** + * Creates an array of shuffled `array` values, using a version of the + * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to shuffle. + * @returns {Array} Returns a new shuffled collection. + * @example + * + * _.shuffle([1, 2, 3, 4, 5, 6]); + * // => [4, 1, 6, 3, 5, 2] + */ + function shuffle(collection) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + var rand = floor(nativeRandom() * (++index + 1)); + result[index] = result[rand]; + result[rand] = value; + }); + return result; + } + + /** + * Gets the size of the `collection` by returning `collection.length` for arrays + * and array-like objects or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to inspect. + * @returns {Number} Returns `collection.length` or number of own enumerable properties. + * @example + * + * _.size([1, 2]); + * // => 2 + * + * _.size({ 'one': 1, 'two': 2, 'three': 3 }); + * // => 3 + * + * _.size('curly'); + * // => 5 + */ + function size(collection) { + var length = collection ? collection.length : 0; + return typeof length == 'number' ? length : keys(collection).length; + } + + /** + * Checks if the `callback` returns a truthy value for **any** element of a + * `collection`. The function returns as soon as it finds passing value, and + * does not iterate over the entire `collection`. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias any + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if any element passes the callback check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.some(food, 'organic'); + * // => true + * + * // using "_.where" callback shorthand + * _.some(food, { 'type': 'meat' }); + * // => false + */ + function some(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if ((result = callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return !(result = callback(value, index, collection)); + }); + } + return !!result; + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in the `collection` through the `callback`. This method + * performs a stable sort, that is, it will preserve the original sort order of + * equal elements. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of sorted elements. + * @example + * + * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * // => [3, 1, 2] + * + * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * // => [3, 1, 2] + * + * // using "_.pluck" callback shorthand + * _.sortBy(['banana', 'strawberry', 'apple'], 'length'); + * // => ['apple', 'banana', 'strawberry'] + */ + function sortBy(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + forEach(collection, function(value, key, collection) { + result[++index] = { + 'criteria': callback(value, key, collection), + 'index': index, + 'value': value + }; + }); + + length = result.length; + result.sort(compareAscending); + while (length--) { + result[length] = result[length].value; + } + return result; + } + + /** + * Converts the `collection` to an array. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to convert. + * @returns {Array} Returns the new converted array. + * @example + * + * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); + * // => [2, 3, 4] + */ + function toArray(collection) { + if (collection && typeof collection.length == 'number') { + return noCharByIndex && isString(collection) + ? collection.split('') + : slice(collection); + } + return values(collection); + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * that have the given `properties`. When checking `properties`, this method + * performs a deep comparison between values to determine if they are equivalent + * to each other. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Object} properties The object of property values to filter by. + * @returns {Array} Returns a new array of elements that have the given `properties`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.where(stooges, { 'age': 40 }); + * // => [{ 'name': 'moe', 'age': 40 }] + */ + var where = filter; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values of `array` removed. The values + * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result.push(value); + } + } + return result; + } + + /** + * Creates an array of `array` elements not present in the other arrays + * using strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {Array} [array1, array2, ...] Arrays to check. + * @returns {Array} Returns a new array of `array` elements not present in the + * other arrays. + * @example + * + * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); + * // => [1, 3, 4] + */ + function difference(array) { + var index = -1, + length = array ? array.length : 0, + flattened = concat.apply(arrayRef, arguments), + contains = cachedContains(flattened, length), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Gets the first element of the `array`. If a number `n` is passed, the first + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the first elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias head, take + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the first element(s) of `array`. + * @example + * + * _.first([1, 2, 3]); + * // => 1 + * + * _.first([1, 2, 3], 2); + * // => [1, 2] + * + * _.first([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [1, 2] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.first(food, 'organic'); + * // => [{ 'name': 'banana', 'organic': true }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.first(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }] + */ + function first(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = -1; + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[0]; + } + } + return slice(array, 0, nativeMin(nativeMax(0, n), length)); + } + } + + /** + * Flattens a nested array (the nesting can be to any depth). If `shallow` is + * truthy, `array` will only be flattened a single level. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @param {Boolean} shallow A flag to indicate only flattening a single level. + * @returns {Array} Returns a new flattened array. + * @example + * + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; + * + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, [[4]]]; + */ + function flatten(array, shallow) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + + // recursively flatten arrays (susceptible to call stack limits) + if (isArray(value)) { + push.apply(result, shallow ? value : flatten(value)); + } else { + result.push(value); + } + } + return result; + } + + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If the `array` is already + * sorted, passing `true` for `fromIndex` will run a faster binary search. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to + * perform a binary search on a sorted `array`. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 + * + * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); + * // => 2 + */ + function indexOf(array, value, fromIndex) { + var index = -1, + length = array ? array.length : 0; + + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1; + } else if (fromIndex) { + index = sortedIndex(array, value); + return array[index] === value ? index : -1; + } + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Gets all but the last element of `array`. If a number `n` is passed, the + * last `n` elements are excluded from the result. If a `callback` function + * is passed, the last elements the `callback` returns truthy for are excluded + * from the result. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + * + * _.initial([1, 2, 3], 2); + * // => [1] + * + * _.initial([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [1] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.initial(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.initial(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'banana', 'type': 'fruit' }] + */ + function initial(array, callback, thisArg) { + if (!array) { + return []; + } + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : callback || n; + } + return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); + } + + /** + * Computes the intersection of all the passed-in arrays using strict equality + * for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique elements that are present + * in **all** of the arrays. + * @example + * + * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2] + */ + function intersection(array) { + var args = arguments, + argsLength = args.length, + cache = { '0': {} }, + index = -1, + length = array ? array.length : 0, + isLarge = length >= 100, + result = [], + seen = result; + + outer: + while (++index < length) { + var value = array[index]; + if (isLarge) { + var key = value + ''; + var inited = hasOwnProperty.call(cache[0], key) + ? !(seen = cache[0][key]) + : (seen = cache[0][key] = []); + } + if (inited || indexOf(seen, value) < 0) { + if (isLarge) { + seen.push(value); + } + var argsIndex = argsLength; + while (--argsIndex) { + if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) { + continue outer; + } + } + result.push(value); + } + } + return result; + } + + /** + * Gets the last element of the `array`. If a number `n` is passed, the last + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the last elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the last element(s) of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + * + * _.last([1, 2, 3], 2); + * // => [2, 3] + * + * _.last([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.last(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.last(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }] + */ + function last(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[length - 1]; + } + } + return slice(array, nativeMax(0, length - n)); + } + } + + /** + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=array.length-1] The index to search from. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var index = array ? array.length : 0; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Creates an object composed from arrays of `keys` and `values`. Pass either + * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or + * two arrays, one of `keys` and one of corresponding `values`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} keys The array of keys. + * @param {Array} [values=[]] The array of values. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. + * @example + * + * _.object(['moe', 'larry'], [30, 40]); + * // => { 'moe': 30, 'larry': 40 } + */ + function object(keys, values) { + var index = -1, + length = keys ? keys.length : 0, + result = {}; + + while (++index < length) { + var key = keys[index]; + if (values) { + result[key] = values[index]; + } else { + result[key[0]] = key[1]; + } + } + return result; + } + + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Number} [start=0] The start of the range. + * @param {Number} end The end of the range. + * @param {Number} [step=1] The value to increment or descrement by. + * @returns {Array} Returns a new range array. + * @example + * + * _.range(10); + * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * + * _.range(1, 11); + * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + * + * _.range(0, 30, 5); + * // => [0, 5, 10, 15, 20, 25] + * + * _.range(0, -10, -1); + * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = +step || 1; + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so V8 will avoid the slower "dictionary" mode + // http://youtu.be/XAqIpGU8ZZk#t=17m25s + var index = -1, + length = nativeMax(0, ceil((end - start) / step)), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * The opposite of `_.initial`, this method gets all but the first value of `array`. + * If a number `n` is passed, the first `n` values are excluded from the result. + * If a `callback` function is passed, the first elements the `callback` returns + * truthy for are excluded from the result. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias drop, tail + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.rest([1, 2, 3]); + * // => [2, 3] + * + * _.rest([1, 2, 3], 2); + * // => [3] + * + * _.rest([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.rest(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.rest(food, { 'type': 'fruit' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }] + */ + function rest(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { + var n = 0, + index = -1, + length = array ? array.length : 0; + + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); + } + return slice(array, n); + } + + /** + * Uses a binary search to determine the smallest index at which the `value` + * should be inserted into `array` in order to maintain the sort order of the + * sorted `array`. If `callback` is passed, it will be executed for `value` and + * each element in `array` to compute their sort ranking. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to iterate over. + * @param {Mixed} value The value to evaluate. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Number} Returns the index at which the value should be inserted + * into `array`. + * @example + * + * _.sortedIndex([20, 30, 50], 40); + * // => 2 + * + * // using "_.pluck" callback shorthand + * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 2 + * + * var dict = { + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * }; + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return dict.wordToNumber[word]; + * }); + * // => 2 + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return this.wordToNumber[word]; + * }, dict); + * // => 2 + */ + function sortedIndex(array, value, callback, thisArg) { + var low = 0, + high = array ? array.length : low; + + // explicitly reference `identity` for better inlining in Firefox + callback = callback ? createCallback(callback, thisArg, 1) : identity; + value = callback(value); + + while (low < high) { + var mid = (low + high) >>> 1; + callback(array[mid]) < value + ? low = mid + 1 + : high = mid; + } + return low; + } + + /** + * Computes the union of the passed-in arrays using strict equality for + * comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique values, in order, that are + * present in one or more of the arrays. + * @example + * + * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2, 3, 101, 10] + */ + function union() { + return uniq(concat.apply(arrayRef, arguments)); + } + + /** + * Creates a duplicate-value-free version of the `array` using strict equality + * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` + * for `isSorted` will run a faster algorithm. If `callback` is passed, each + * element of `array` is passed through a callback` before uniqueness is computed. + * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias unique + * @category Arrays + * @param {Array} array The array to process. + * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a duplicate-value-free array. + * @example + * + * _.uniq([1, 2, 1, 3, 1]); + * // => [1, 2, 3] + * + * _.uniq([1, 1, 2, 2, 3], true); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); }); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math); + * // => [1, 2, 3] + * + * // using "_.pluck" callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniq(array, isSorted, callback, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = [], + seen = result; + + // juggle arguments + if (typeof isSorted == 'function') { + thisArg = callback; + callback = isSorted; + isSorted = false; + } + // init value cache for large arrays + var isLarge = !isSorted && length >= 75; + if (isLarge) { + var cache = {}; + } + if (callback) { + seen = []; + callback = createCallback(callback, thisArg); + } + while (++index < length) { + var value = array[index], + computed = callback ? callback(value, index, array) : value; + + if (isLarge) { + var key = computed + ''; + var inited = hasOwnProperty.call(cache, key) + ? !(seen = cache[key]) + : (seen = cache[key] = []); + } + if (isSorted + ? !index || seen[seen.length - 1] !== computed + : inited || indexOf(seen, computed) < 0 + ) { + if (callback || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * Creates an array with all occurrences of the passed values removed using + * strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to filter. + * @param {Mixed} [value1, value2, ...] Values to remove. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] + */ + function without(array) { + var index = -1, + length = array ? array.length : 0, + contains = cachedContains(arguments, 1), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Groups the elements of each array at their corresponding indexes. Useful for + * separate data sources that are coordinated through matching array indexes. + * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix + * in a similar fashion. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of grouped elements. + * @example + * + * _.zip(['moe', 'larry'], [30, 40], [true, false]); + * // => [['moe', 30, true], ['larry', 40, false]] + */ + function zip(array) { + var index = -1, + length = array ? max(pluck(arguments, 'length')) : 0, + result = Array(length); + + while (++index < length) { + result[index] = pluck(arguments, index); + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function that is restricted to executing `func` only after it is + * called `n` times. The `func` is executed with the `this` binding of the + * created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Number} n The number of times the function must be called before + * it is executed. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var renderNotes = _.after(notes.length, render); + * _.forEach(notes, function(note) { + * note.asyncSave({ 'success': renderNotes }); + * }); + * // `renderNotes` is run once, after all notes have saved + */ + function after(n, func) { + if (n < 1) { + return func(); + } + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * passed to the bound function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to bind. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var func = function(greeting) { + * return greeting + ' ' + this.name; + * }; + * + * func = _.bind(func, { 'name': 'moe' }, 'hi'); + * func(); + * // => 'hi moe' + */ + function bind(func, thisArg) { + // use `Function#bind` if it exists and is fast + // (in V8 `Function#bind` is slower except when partially applied) + return isBindFast || (nativeBind && arguments.length > 2) + ? nativeBind.call.apply(nativeBind, arguments) + : createBound(func, thisArg, slice(arguments, 2)); + } + + /** + * Binds methods on `object` to `object`, overwriting the existing method. + * Method names may be specified as individual arguments or as arrays of method + * names. If no method names are provided, all the function properties of `object` + * will be bound. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object to bind and assign the bound methods to. + * @param {String} [methodName1, methodName2, ...] Method names on the object to bind. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'onClick': function() { alert('clicked ' + this.label); } + * }; + * + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => alerts 'clicked docs', when the button is clicked + */ + function bindAll(object) { + var funcs = concat.apply(arrayRef, arguments), + index = funcs.length > 1 ? 0 : (funcs = functions(object), -1), + length = funcs.length; + + while (++index < length) { + var key = funcs[index]; + object[key] = bind(object[key], object); + } + return object; + } + + /** + * Creates a function that, when called, invokes the method at `object[key]` + * and prepends any additional `bindKey` arguments to those passed to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. + * See http://michaux.ca/articles/lazy-function-definition-pattern. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object the method belongs to. + * @param {String} key The key of the method. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'name': 'moe', + * 'greet': function(greeting) { + * return greeting + ' ' + this.name; + * } + * }; + * + * var func = _.bindKey(object, 'greet', 'hi'); + * func(); + * // => 'hi moe' + * + * object.greet = function(greeting) { + * return greeting + ', ' + this.name + '!'; + * }; + * + * func(); + * // => 'hi, moe!' + */ + function bindKey(object, key) { + return createBound(object, key, slice(arguments, 2)); + } + + /** + * Creates a function that is the composition of the passed functions, + * where each function consumes the return value of the function that follows. + * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * Each function is executed with the `this` binding of the composed function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} [func1, func2, ...] Functions to compose. + * @returns {Function} Returns the new composed function. + * @example + * + * var greet = function(name) { return 'hi ' + name; }; + * var exclaim = function(statement) { return statement + '!'; }; + * var welcome = _.compose(exclaim, greet); + * welcome('moe'); + * // => 'hi moe!' + */ + function compose() { + var funcs = arguments; + return function() { + var args = arguments, + length = funcs.length; + + while (length--) { + args = [funcs[length].apply(this, args)]; + } + return args[0]; + }; + } + + /** + * Creates a function that will delay the execution of `func` until after + * `wait` milliseconds have elapsed since the last time it was invoked. Pass + * `true` for `immediate` to cause debounce to invoke `func` on the leading, + * instead of the trailing, edge of the `wait` timeout. Subsequent calls to + * the debounced function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to debounce. + * @param {Number} wait The number of milliseconds to delay. + * @param {Boolean} immediate A flag to indicate execution is on the leading + * edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * var lazyLayout = _.debounce(calculateLayout, 300); + * jQuery(window).on('resize', lazyLayout); + */ + function debounce(func, wait, immediate) { + var args, + result, + thisArg, + timeoutId; + + function delayed() { + timeoutId = null; + if (!immediate) { + result = func.apply(thisArg, args); + } + } + return function() { + var isImmediate = immediate && !timeoutId; + args = arguments; + thisArg = this; + + clearTimeout(timeoutId); + timeoutId = setTimeout(delayed, wait); + + if (isImmediate) { + result = func.apply(thisArg, args); + } + return result; + }; + } + + /** + * Executes the `func` function after `wait` milliseconds. Additional arguments + * will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to delay. + * @param {Number} wait The number of milliseconds to delay execution. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * var log = _.bind(console.log, console); + * _.delay(log, 1000, 'logged later'); + * // => 'logged later' (Appears after one second.) + */ + function delay(func, wait) { + var args = slice(arguments, 2); + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * Defers executing the `func` function until the current call stack has cleared. + * Additional arguments will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to defer. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * _.defer(function() { alert('deferred'); }); + * // returns from the function before `alert` is called + */ + function defer(func) { + var args = slice(arguments, 1); + return setTimeout(function() { func.apply(undefined, args); }, 1); + } + // use `setImmediate` if it's available in Node.js + if (isV8 && freeModule && typeof setImmediate == 'function') { + defer = bind(setImmediate, window); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * passed, it will be used to determine the cache key for storing the result + * based on the arguments passed to the memoized function. By default, the first + * argument passed to the memoized function is used as the cache key. The `func` + * is executed with the `this` binding of the memoized function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] A function used to resolve the cache key. + * @returns {Function} Returns the new memoizing function. + * @example + * + * var fibonacci = _.memoize(function(n) { + * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * }); + */ + function memoize(func, resolver) { + var cache = {}; + return function() { + var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + ''; + return hasOwnProperty.call(cache, key) + ? cache[key] + : (cache[key] = func.apply(this, arguments)); + }; + } + + /** + * Creates a function that is restricted to execute `func` once. Repeat calls to + * the function will return the value of the first call. The `func` is executed + * with the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` executes `createApplication` once + */ + function once(func) { + var ran, + result; + + return function() { + if (ran) { + return result; + } + ran = true; + result = func.apply(this, arguments); + + // clear the `func` variable so the function may be garbage collected + func = null; + return result; + }; + } + + /** + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those passed to the new function. This + * method is similar to `_.bind`, except it does **not** alter the `this` binding. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var hi = _.partial(greet, 'hi'); + * hi('moe'); + * // => 'hi moe' + */ + function partial(func) { + return createBound(func, slice(arguments, 1)); + } + + /** + * This method is similar to `_.partial`, except that `partial` arguments are + * appended to those passed to the new function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var defaultsDeep = _.partialRight(_.merge, _.defaults); + * + * var options = { + * 'variable': 'data', + * 'imports': { 'jq': $ } + * }; + * + * defaultsDeep(options, _.templateSettings); + * + * options.variable + * // => 'data' + * + * options.imports + * // => { '_': _, 'jq': $ } + */ + function partialRight(func) { + return createBound(func, slice(arguments, 1), null, indicatorObject); + } + + /** + * Creates a function that, when executed, will only call the `func` + * function at most once per every `wait` milliseconds. If the throttled + * function is invoked more than once during the `wait` timeout, `func` will + * also be called on the trailing edge of the timeout. Subsequent calls to the + * throttled function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to throttle. + * @param {Number} wait The number of milliseconds to throttle executions to. + * @returns {Function} Returns the new throttled function. + * @example + * + * var throttled = _.throttle(updatePosition, 100); + * jQuery(window).on('scroll', throttled); + */ + function throttle(func, wait) { + var args, + result, + thisArg, + timeoutId, + lastCalled = 0; + + function trailingCall() { + lastCalled = new Date; + timeoutId = null; + result = func.apply(thisArg, args); + } + return function() { + var now = new Date, + remaining = wait - (now - lastCalled); + + args = arguments; + thisArg = this; + + if (remaining <= 0) { + clearTimeout(timeoutId); + timeoutId = null; + lastCalled = now; + result = func.apply(thisArg, args); + } + else if (!timeoutId) { + timeoutId = setTimeout(trailingCall, remaining); + } + return result; + }; + } + + /** + * Creates a function that passes `value` to the `wrapper` function as its + * first argument. Additional arguments passed to the function are appended + * to those passed to the `wrapper` function. The `wrapper` is executed with + * the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Mixed} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var hello = function(name) { return 'hello ' + name; }; + * hello = _.wrap(hello, function(func) { + * return 'before, ' + func('moe') + ', after'; + * }); + * hello(); + * // => 'before, hello moe, after' + */ + function wrap(value, wrapper) { + return function() { + var args = [value]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their + * corresponding HTML entities. + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} string The string to escape. + * @returns {String} Returns the escaped string. + * @example + * + * _.escape('Moe, Larry & Curly'); + * // => 'Moe, Larry & Curly' + */ + function escape(string) { + return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * This function returns the first argument passed to it. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Mixed} value Any value. + * @returns {Mixed} Returns `value`. + * @example + * + * var moe = { 'name': 'moe' }; + * moe === _.identity(moe); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Adds functions properties of `object` to the `lodash` function and chainable + * wrapper. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object of function properties to add to `lodash`. + * @example + * + * _.mixin({ + * 'capitalize': function(string) { + * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + * } + * }); + * + * _.capitalize('moe'); + * // => 'Moe' + * + * _('moe').capitalize(); + * // => 'Moe' + */ + function mixin(object) { + forEach(functions(object), function(methodName) { + var func = lodash[methodName] = object[methodName]; + + lodash.prototype[methodName] = function() { + var args = [this.__wrapped__]; + push.apply(args, arguments); + return new lodash(func.apply(lodash, args)); + }; + }); + } + + /** + * Reverts the '_' variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Utilities + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + window._ = oldDash; + return this; + } + + /** + * Produces a random number between `min` and `max` (inclusive). If only one + * argument is passed, a number between `0` and the given number will be returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Number} [min=0] The minimum possible value. + * @param {Number} [max=1] The maximum possible value. + * @returns {Number} Returns a random number. + * @example + * + * _.random(0, 5); + * // => a number between 0 and 5 + * + * _.random(5); + * // => also a number between 0 and 5 + */ + function random(min, max) { + if (min == null && max == null) { + max = 1; + } + min = +min || 0; + if (max == null) { + max = min; + min = 0; + } + return min + floor(nativeRandom() * ((+max || 0) - min + 1)); + } + + /** + * Resolves the value of `property` on `object`. If `property` is a function, + * it will be invoked and its result returned, else the property value is + * returned. If `object` is falsey, then `null` is returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object to inspect. + * @param {String} property The property to get the value of. + * @returns {Mixed} Returns the resolved value. + * @example + * + * var object = { + * 'cheese': 'crumpets', + * 'stuff': function() { + * return 'nonsense'; + * } + * }; + * + * _.result(object, 'cheese'); + * // => 'crumpets' + * + * _.result(object, 'stuff'); + * // => 'nonsense' + */ + function result(object, property) { + var value = object ? object[property] : undefined; + return isFunction(value) ? object[property]() : value; + } + + /** + * A micro-templating method that handles arbitrary delimiters, preserves + * whitespace, and correctly escapes quotes within interpolated code. + * + * Note: In the development build, `_.template` utilizes sourceURLs for easier + * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl + * + * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` + * build and using precompiled templates, or loading Lo-Dash in a sandbox. + * + * For more information on precompiling templates see: + * http://lodash.com/#custom-builds + * + * For more information on Chrome extension sandboxes see: + * http://developer.chrome.com/stable/extensions/sandboxingEval.html + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} text The template text. + * @param {Obect} data The data object used to populate the text. + * @param {Object} options The options object. + * escape - The "escape" delimiter regexp. + * evaluate - The "evaluate" delimiter regexp. + * interpolate - The "interpolate" delimiter regexp. + * sourceURL - The sourceURL of the template's compiled source. + * variable - The data object variable name. + * + * @returns {Function|String} Returns a compiled function when no `data` object + * is given, else it returns the interpolated text. + * @example + * + * // using a compiled template + * var compiled = _.template('hello <%= name %>'); + * compiled({ 'name': 'moe' }); + * // => 'hello moe' + * + * var list = '<% _.forEach(people, function(name) { %>
  • <%= name %>
  • <% }); %>'; + * _.template(list, { 'people': ['moe', 'larry'] }); + * // => '
  • moe
  • larry
  • ' + * + * // using the "escape" delimiter to escape HTML in data property values + * _.template('<%- value %>', { 'value': '\n```\n\nUsing [`npm`](http://npmjs.org/):\n\n```bash\nnpm install lodash\n\nnpm install -g lodash\nnpm link lodash\n```\n\nTo avoid potential issues, update `npm` before installing Lo-Dash:\n\n```bash\nnpm install npm -g\n```\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n\n// or as a drop-in replacement for Underscore\nvar _ = require('lodash/lodash.underscore');\n```\n\n**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it.\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n```js\nvar _ = require('lodash')._;\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire({\n 'paths': {\n 'underscore': 'path/to/lodash'\n }\n},\n['underscore'], function(_) {\n console.log(_.VERSION);\n});\n```\n\n## Release Notes\n\n### v1.0.1\n\n * Add support for specifying source map URLs in `-p`/`--source-map` build options\n * Ensured the second argument passed to `_.assign` is not treated as a `callback`\n * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`\n * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed\n * Made `_.defer` use `setImmediate`, in Node.js, when available\n * Made `_.where` search arrays for values regardless of their index position\n * Removed dead code from `_.template`\n\nThe full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog).\n\n## BestieJS\n\nLo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.\n\n## Author\n\n| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton \"Follow @jdalton on Twitter\") |\n|---|\n| [John-David Dalton](http://allyoucanleet.com/) |\n\n## Contributors\n\n| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz \"Follow @BlaineBublitz on Twitter\") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias \"Follow @mathias on Twitter\") |\n|---|---|---|\n| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) |\n", + "readmeFilename": "README.md", + "_id": "lodash@1.0.1", + "_from": "lodash@~1.0.1" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md new file mode 100644 index 000000000..6fd07d2e9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md @@ -0,0 +1,218 @@ +# minimatch + +A minimal matching utility. + +[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch) + + +This is the matching library used internally by npm. + +Eventually, it will replace the C binding in node-glob. + +It works by converting glob expressions into JavaScript `RegExp` +objects. + +## Usage + +```javascript +var minimatch = require("minimatch") + +minimatch("bar.foo", "*.foo") // true! +minimatch("bar.foo", "*.bar") // false! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +### Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between minimatch and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. **Note that this is different from the way that `**` is +handled by ruby's `Dir` class.** + +If an escaped pattern has no matches, and the `nonull` flag is set, +then minimatch.match returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + + +## Minimatch Class + +Create a minimatch object by instanting the `minimatch.Minimatch` class. + +```javascript +var Minimatch = require("minimatch").Minimatch +var mm = new Minimatch(pattern, options) +``` + +### Properties + +* `pattern` The original pattern the minimatch object represents. +* `options` The options supplied to the constructor. +* `set` A 2-dimensional array of regexp or string expressions. + Each row in the + array corresponds to a brace-expanded pattern. Each item in the row + corresponds to a single path-part. For example, the pattern + `{a,b/c}/d` would expand to a set of patterns like: + + [ [ a, d ] + , [ b, c, d ] ] + + If a portion of the pattern doesn't have any "magic" in it + (that is, it's something like `"foo"` rather than `fo*o?`), then it + will be left as a string rather than converted to a regular + expression. + +* `regexp` Created by the `makeRe` method. A single regular expression + expressing the entire pattern. This is useful in cases where you wish + to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. +* `negate` True if the pattern is negated. +* `comment` True if the pattern is a comment. +* `empty` True if the pattern is `""`. + +### Methods + +* `makeRe` Generate the `regexp` member if necessary, and return it. + Will return `false` if the pattern is invalid. +* `match(fname)` Return true if the filename matches the pattern, or + false otherwise. +* `matchOne(fileArray, patternArray, partial)` Take a `/`-split + filename, and match it against a single row in the `regExpSet`. This + method is mainly for internal use, but is exposed so that it can be + used by a glob-walker that needs to avoid excessive filesystem calls. + +All other methods are internal, and will be called as necessary. + +## Functions + +The top-level exported function has a `cache` property, which is an LRU +cache set to store 100 items. So, calling these methods repeatedly +with the same pattern and options will use the same Minimatch object, +saving the cost of parsing it multiple times. + +### minimatch(path, pattern, options) + +Main export. Tests a path against the pattern using the options. + +```javascript +var isJS = minimatch(file, "*.js", { matchBase: true }) +``` + +### minimatch.filter(pattern, options) + +Returns a function that tests its +supplied argument, suitable for use with `Array.filter`. Example: + +```javascript +var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) +``` + +### minimatch.match(list, pattern, options) + +Match against the list of +files, in the style of fnmatch or glob. If nothing is matched, and +options.nonull is set, then return a list containing the pattern itself. + +```javascript +var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) +``` + +### minimatch.makeRe(pattern, options) + +Make a regular expression object from the pattern. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### nobrace + +Do not expand `{a,b}` and `{1..3}` brace sets. + +### noglobstar + +Disable `**` matching against multiple folder names. + +### dot + +Allow patterns to match filenames starting with a period, even if +the pattern does not explicitly have a period in that spot. + +Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` +is set. + +### noext + +Disable "extglob" style patterns like `+(a|b)`. + +### nocase + +Perform a case-insensitive match. + +### nonull + +When a match is not found by `minimatch.match`, return a list containing +the pattern itself. When set, an empty list is returned if there are +no matches. + +### matchBase + +If set, then patterns without slashes will be matched +against the basename of the path if it contains slashes. For example, +`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + +### nocomment + +Suppress the behavior of treating `#` at the start of a pattern as a +comment. + +### nonegate + +Suppress the behavior of treating a leading `!` character as negation. + +### flipNegate + +Returns from negate expressions the same as if they were not negated. +(Ie, true on a hit, false on a miss.) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js new file mode 100644 index 000000000..405746b67 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js @@ -0,0 +1,1079 @@ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.monkeyPatch = monkeyPatch +function monkeyPatch () { + var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") + var orig = desc.value + desc.value = function (p) { + if (p instanceof Minimatch) return p.match(this) + return orig.call(this, p) + } + Object.defineProperty(String.prototype, desc) +} + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) console.error(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + if (options.debug) console.error(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + if (options.debug) console.error(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + if (options.debug) console.error(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + // console.error(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + // console.error("no sets") + return [pattern] + } + + var tail = braceExpand(pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + // console.error("numset", numset[1], numset[2]) + var suf = braceExpand(pattern.substr(numset[0].length), options) + , start = +numset[1] + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + for (var i = start; i != (end + inc); i += inc) { + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(i + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + // console.error("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + // console.error("didn't close", pattern) + return braceExpand("\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + // console.error("set", set) + // console.error("suffix", pattern.substr(i)) + var suf = braceExpand(pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + // console.error("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand(p, options) + }) + // console.error("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + if (options.debug) { + console.error("%s\t%s %s %j", pattern, i, re, c) + } + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + if (options.debug) { + console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + } + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + // console.error("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + // console.error("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + if (options.debug) { + console.error(this.pattern, "split", f) + } + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + // console.error(this.pattern, "set", set) + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i] + var hit = this.matchOne(f, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + if (options.debug) { + console.error("matchOne", + { "this": this + , file: file + , pattern: pattern }) + } + + if (options.matchBase && pattern.length === 1) { + file = path.basename(file.join("/")).split("/") + } + + if (options.debug) { + console.error("matchOne", file.length, pattern.length) + } + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + if (options.debug) { + console.error("matchOne loop") + } + var p = pattern[pi] + , f = file[fi] + + if (options.debug) { + console.error(pattern, p, f) + } + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + if (options.debug) + console.error('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + if (options.debug) + console.error('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + if (options.debug) { + console.error('\nglobstar while', + file, fr, pattern, pr, swallowee) + } + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + if (options.debug) + console.error('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + if (options.debug) + console.error("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + if (options.debug) + console.error('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + // console.error("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + if (options.debug) { + console.error("string match", p, f, hit) + } + } else { + hit = f.match(p) + if (options.debug) { + console.error("pattern match", p, f, hit) + } + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 000000000..07e6e472c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/AUTHORS b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/AUTHORS new file mode 100644 index 000000000..016d7fbe1 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 000000000..03ee0f985 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,97 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/bench.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/bench.js new file mode 100644 index 000000000..91115400b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/bench.js @@ -0,0 +1,25 @@ +var LRU = require('lru-cache'); + +var max = +process.argv[2] || 10240; +var more = 102400; + +var cache = LRU({ + max: max, maxAge: 86400e3 +}); + +// fill cache +for (var i = 0; i < max; ++i) { + cache.set(i, {}); +} + +var start = process.hrtime(); + +// adding more items +for ( ; i < max+more; ++i) { + cache.set(i, {}); +} + +var end = process.hrtime(start); +var msecs = end[0] * 1E3 + end[1] / 1E6; + +console.log('adding %d items took %d ms', more, msecs.toPrecision(5)); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 000000000..49c1dc6de --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,263 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) { + return new LRUCache(options) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + + if (!options) options = {} + + max = options.max + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var allowStale = options.stale || false + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , lru = 0 // least recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + i++ + var hit = lruList[k] + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } + } + + this.keys = function () { + var keys = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + keys[i++] = hit.key + } + return keys + } + + this.values = function () { + var values = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + values[i++] = hit.value + } + return values + } + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.dumpLru = function () { + return lruList + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.has = function (key) { + if (!hOP(cache, key)) return false + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + return false + } + return true + } + + this.get = function (key) { + return get(key, true) + } + + this.peek = function (key) { + return get(key, false) + } + + function get (key, doUse) { + var hit = cache[key] + if (hit) { + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } else { + if (doUse) use(hit) + } + if (hit) hit = hit.value + } + return hit + } + + function use (hit) { + shiftLU(hit) + hit.lu = mru ++ + lruList[hit.lu] = hit + } + + this.del = function (key) { + del(cache[key]) + } + + function trim () { + while (lru < mru && length > max) + del(lruList[lru]) + } + + function shiftLU(hit) { + delete lruList[ hit.lu ] + while (lru < mru && !lruList[lru]) lru ++ + } + + function del(hit) { + if (hit) { + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + itemCount -- + delete cache[ hit.key ] + shiftLU(hit) + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 000000000..411acad3b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,62 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.3.1", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `peek(key)`\n\n Returns the key value (or `undefined` if not found) without\n updating the \"recently used\"-ness of the key.\n\n (If you find yourself using this a lot, you *might* be using the\n wrong sort of data structure, but there are some use cases where\n it's handy.)\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "_id": "lru-cache@2.3.1", + "_from": "lru-cache@2" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 000000000..70f3f8beb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,329 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js new file mode 100644 index 000000000..eefb80d9d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 000000000..7af45b022 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 000000000..7e365129e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md @@ -0,0 +1,53 @@ +# sigmund + +Quick and dirty signatures for Objects. + +This is like a much faster `deepEquals` comparison, which returns a +string key suitable for caches and the like. + +## Usage + +```javascript +function doSomething (someObj) { + var key = sigmund(someObj, maxDepth) // max depth defaults to 10 + var cached = cache.get(key) + if (cached) return cached) + + var result = expensiveCalculation(someObj) + cache.set(key, result) + return result +} +``` + +The resulting key will be as unique and reproducible as calling +`JSON.stringify` or `util.inspect` on the object, but is much faster. +In order to achieve this speed, some differences are glossed over. +For example, the object `{0:'foo'}` will be treated identically to the +array `['foo']`. + +Also, just as there is no way to summon the soul from the scribblings +of a cocain-addled psychoanalyst, there is no way to revive the object +from the signature string that sigmund gives you. In fact, it's +barely even readable. + +As with `sys.inspect` and `JSON.stringify`, larger objects will +produce larger signature strings. + +Because sigmund is a bit less strict than the more thorough +alternatives, the strings will be shorter, and also there is a +slightly higher chance for collisions. For example, these objects +have the same signature: + + var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} + var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +Like a good Freudian, sigmund is most effective when you already have +some understanding of what you're looking for. It can help you help +yourself, but you must be willing to do some work as well. + +Cycles are handled, and cyclical objects are silently omitted (though +the key is included in the signature output.) + +The second argument is the maximum depth, which defaults to 10, +because that is the maximum object traversal depth covered by most +insurance carriers. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 000000000..5acfd6d90 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js @@ -0,0 +1,283 @@ +// different ways to id objects +// use a req/res pair, since it's crazy deep and cyclical + +// sparseFE10 and sigmund are usually pretty close, which is to be expected, +// since they are essentially the same algorithm, except that sigmund handles +// regular expression objects properly. + + +var http = require('http') +var util = require('util') +var sigmund = require('./sigmund.js') +var sreq, sres, creq, cres, test + +http.createServer(function (q, s) { + sreq = q + sres = s + sres.end('ok') + this.close(function () { setTimeout(function () { + start() + }, 200) }) +}).listen(1337, function () { + creq = http.get({ port: 1337 }) + creq.on('response', function (s) { cres = s }) +}) + +function start () { + test = [sreq, sres, creq, cres] + // test = sreq + // sreq.sres = sres + // sreq.creq = creq + // sreq.cres = cres + + for (var i in exports.compare) { + console.log(i) + var hash = exports.compare[i]() + console.log(hash) + console.log(hash.length) + console.log('') + } + + require('bench').runMain() +} + +function customWs (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '') + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return customWs(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + customWs(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function custom (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return '' + obj + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return custom(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + custom(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function sparseFE2 (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ':' + ch(v[k], depth + 1) + }) + soFar += '}' + } + ch(obj, 0) + return soFar +} + +function sparseFE (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ch(v[k], depth + 1) + }) + } + ch(obj, 0) + return soFar +} + +function sparse (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ch(v[k], depth + 1) + } + } + ch(obj, 0) + return soFar +} + +function noCommas (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + + +function flatten (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + soFar += ',' + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + +exports.compare = +{ + // 'custom 2': function () { + // return custom(test, 2, 0) + // }, + // 'customWs 2': function () { + // return customWs(test, 2, 0) + // }, + 'JSON.stringify (guarded)': function () { + var seen = [] + return JSON.stringify(test, function (k, v) { + if (typeof v !== 'object' || !v) return v + if (seen.indexOf(v) !== -1) return undefined + seen.push(v) + return v + }) + }, + + 'flatten 10': function () { + return flatten(test, 10) + }, + + // 'flattenFE 10': function () { + // return flattenFE(test, 10) + // }, + + 'noCommas 10': function () { + return noCommas(test, 10) + }, + + 'sparse 10': function () { + return sparse(test, 10) + }, + + 'sparseFE 10': function () { + return sparseFE(test, 10) + }, + + 'sparseFE2 10': function () { + return sparseFE2(test, 10) + }, + + sigmund: function() { + return sigmund(test, 10) + }, + + + // 'util.inspect 1': function () { + // return util.inspect(test, false, 1, false) + // }, + // 'util.inspect undefined': function () { + // util.inspect(test) + // }, + // 'util.inspect 2': function () { + // util.inspect(test, false, 2, false) + // }, + // 'util.inspect 3': function () { + // util.inspect(test, false, 3, false) + // }, + // 'util.inspect 4': function () { + // util.inspect(test, false, 4, false) + // }, + // 'util.inspect Infinity': function () { + // util.inspect(test, false, Infinity, false) + // } +} + +/** results +**/ diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 000000000..ec8e2eb3e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,41 @@ +{ + "name": "sigmund", + "version": "1.0.0", + "description": "Quick and dirty signatures for Objects.", + "main": "sigmund.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.0" + }, + "scripts": { + "test": "tap test/*.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/sigmund" + }, + "keywords": [ + "object", + "signature", + "key", + "data", + "psychoanalysis" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "BSD", + "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/sigmund/issues" + }, + "_id": "sigmund@1.0.0", + "_from": "sigmund@~1.0.0" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 000000000..82c7ab8ce --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -0,0 +1,39 @@ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 000000000..50c53a13e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -0,0 +1,24 @@ +var test = require('tap').test +var sigmund = require('../sigmund.js') + + +// occasionally there are duplicates +// that's an acceptable edge-case. JSON.stringify and util.inspect +// have some collision potential as well, though less, and collision +// detection is expensive. +var hash = '{abc/def/g{0h1i2{jkl' +var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} +var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +var obj3 = JSON.parse(JSON.stringify(obj1)) +obj3.c = /def/ +obj3.g[2].cycle = obj3 +var cycleHash = '{abc/def/g{0h1i2{jklcycle' + +test('basic', function (t) { + t.equal(sigmund(obj1), hash) + t.equal(sigmund(obj2), hash) + t.equal(sigmund(obj3), cycleHash) + t.end() +}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json new file mode 100644 index 000000000..a34740535 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.2.12", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE" + }, + "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n### Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n Each row in the\n array corresponds to a brace-expanded pattern. Each item in the row\n corresponds to a single path-part. For example, the pattern\n `{a,b/c}/d` would expand to a set of patterns like:\n\n [ [ a, d ]\n , [ b, c, d ] ]\n\n If a portion of the pattern doesn't have any \"magic\" in it\n (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n will be left as a string rather than converted to a regular\n expression.\n\n* `regexp` Created by the `makeRe` method. A single regular expression\n expressing the entire pattern. This is useful in cases where you wish\n to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n filename, and match it against a single row in the `regExpSet`. This\n method is mainly for internal use, but is exposed so that it can be\n used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items. So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`. Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob. If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself. When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes. For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/minimatch/issues" + }, + "_id": "minimatch@0.2.12", + "_from": "minimatch@~0.2.11" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js new file mode 100644 index 000000000..ae7ac73c7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js @@ -0,0 +1,399 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + + +var patterns = + [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + // https://github.com/isaacs/minimatch/issues/5 + , function () { + files = [ 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' + , 'a/b/.x' + , 'a/b/.x/' + , 'a/.x/b' + , '.x' + , '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b/.x/c' + , '.x/.x' ] + } + , ["**/.x/**", [ '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b' + , 'a/b/.x/' + , 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' ] ] + + ] + +var regexps = + [ '/^(?:(?=.)a[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:\\*)$/', + '/^(?:(?=.)\\*[^/]*?)$/', + '/^(?:\\*\\*)$/', + '/^(?:(?=.)b[^/]*?\\/)$/', + '/^(?:(?=.)c[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/', + '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/', + '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/', + '/^(?:(?=.)a[^/]*?[^c])$/', + '/^(?:(?=.)a[X-]b)$/', + '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/', + '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[^/]c)$/', + '/^(?:a\\*c)$/', + 'false', + '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/', + '/^(?:man\\/man1\\/bash\\.1)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[-abc])$/', + '/^(?:(?!\\.)(?=.)[abc-])$/', + '/^(?:\\\\)$/', + '/^(?:(?!\\.)(?=.)[\\\\])$/', + '/^(?:(?!\\.)(?=.)[\\[])$/', + '/^(?:\\[)$/', + '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[\\]])$/', + '/^(?:(?!\\.)(?=.)[\\]-])$/', + '/^(?:(?!\\.)(?=.)[a-z])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:\\[\\])$/', + '/^(?:\\[abc)$/', + '/^(?:(?=.)XYZ)$/i', + '/^(?:(?=.)ab[^/]*?)$/i', + '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i', + '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/', + '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/', + '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/', + '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/', + '/^(?:(?=.)a[^/]b)$/', + '/^(?:(?=.)#[^/]*?)$/', + '/^(?!^(?:(?=.)a[^/]*?)$).*$/', + '/^(?:(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)a[^/]*?)$/', + '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ] +var re = 0; + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + patterns.forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var m = new mm.Minimatch(pattern, options) + var r = m.makeRe() + var expectRe = regexps[re++] + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + + t.equal(tapOpts.re, expectRe, tapOpts) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js new file mode 100644 index 000000000..7ee278a27 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js new file mode 100644 index 000000000..0fec4b0fa --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js new file mode 100644 index 000000000..25f1f601c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json new file mode 100644 index 000000000..feda8e4e6 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json @@ -0,0 +1,60 @@ +{ + "name": "globule", + "description": "An easy-to-use wildcard globbing library.", + "version": "0.1.0", + "homepage": "https://github.com/cowboy/node-globule", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/cowboy/node-globule.git" + }, + "bugs": { + "url": "https://github.com/cowboy/node-globule/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cowboy/node-globule/blob/master/LICENSE-MIT" + } + ], + "main": "lib/globule", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt nodeunit" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-nodeunit": "~0.1.2", + "grunt-contrib-watch": "~0.2.0", + "grunt": "~0.4.1" + }, + "keywords": [ + "glob", + "file", + "match", + "mapping", + "expand", + "wildcard", + "pattern", + "sync", + "awesome" + ], + "dependencies": { + "lodash": "~1.0.1", + "glob": "~3.1.21", + "minimatch": "~0.2.11" + }, + "readme": "# globule [![Build Status](https://secure.travis-ci.org/cowboy/node-globule.png?branch=master)](http://travis-ci.org/cowboy/node-globule)\n\nAn easy-to-use wildcard globbing library.\n\n## Getting Started\nInstall the module with: `npm install globule`\n\n```javascript\nvar globule = require('globule');\nvar filepaths = globule.find('**/*.js');\n```\n\n## Documentation\n\n### globule.find\nReturns a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\nglobule.find(patterns [, options])\n```\n\nThe `options` object supports all [glob][] library options, along with a few extras. These are the most commonly used:\n\n* `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that will be passed the matched `src` filepath and `options` object as arguments. This function should return a `Boolean` value.\n* `nonull` Retain globbing patterns in result set even if they fail to match files.\n* `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`.\n* `srcBase` Patterns will be matched relative to the specified path instead of the current working directory. This is a synonym for `cwd`.\n* `prefixBase` Any specified `srcBase` will be prefixed to all returned filepaths.\n\n[glob]: https://github.com/isaacs/node-glob\n\n### globule.match\nMatch one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` arguments can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\ngrunt.file.match(patterns, filepaths [, options])\n```\n\n### globule.isMatch\nThis method contains the same signature and logic as the `globule.match` method, but returns `true` if any files were matched, otherwise `false`.\n\n```js\ngrunt.file.isMatch(patterns, filepaths [, options])\n```\n\n### globule.mapping\nGiven a set of source file paths, returns an array of src-dest file mapping objects. Both src and dest paths may be renamed, depending on the options specified.\n\n```js\nglobule.mapping(filepaths [, options])\n```\n\nIn addition to the options the `globule.find` method supports, the options object also supports these properties:\n\n* `srcBase` The directory from which patterns are matched. Any string specified as `srcBase` is effectively stripped from the beginning of all matched paths.\n* `destBase` The specified path is prefixed to all `dest` filepaths.\n* `ext` Remove anything after (and including) the first `.` in the destination path, then append this value.\n* `extDot` Change the behavior of `ext`, `\"first\"` and `\"last\"` will remove anything after the first or last `.` in the destination filename, respectively. Defaults to `\"first\"`.\n* `flatten` Remove the path component from all matched src files. The src file path is still joined to the specified destBase.\n* `rename` If specified, this function will be responsible for returning the final `dest` filepath. By default, it flattens paths (if specified), changes extensions (if specified) and joins the matched path to the `destBase`.\n\n### globule.findMapping\nThis method is a convenience wrapper around the `globule.find` and `globule.mapping` methods.\n\n```js\nglobule.findMapping(patterns [, options])\n```\n\n\n## Examples\n\nGiven the files `foo/a.js` and `foo/b.js`:\n\n### srcBase and destBase\n\n```js\nglobule.find(\"foo/*.js\")\n// [\"foo/a.js\", \"foo/b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\"})\n// [\"a.js\", \"b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\", prefixBase: true})\n// [\"foo/a.js\", \"foo/b.js\"]\n```\n\n```js\nglobule.findMapping(\"foo/*.js\")\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.findMapping(\"foo/*.js\", {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.findMapping(\"*.js\", {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n```js\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"])\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"], {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.mapping([\"a.js\", \"b.js\"], {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\n\n## Release History\n_(Nothing yet)_\n\n## License\nCopyright (c) 2013 \"Cowboy\" Ben Alman \nLicensed under the MIT license.\n", + "readmeFilename": "README.md", + "_id": "globule@0.1.0", + "dist": { + "shasum": "7f4a9b4cb54dbf09331bafe37ea400bd67b4f6e5" + }, + "_from": "globule@~0.1.0", + "_resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/baz.css b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/baz.css new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/qux.css b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/qux.css new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deep.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deep.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deeper.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deeper.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deepest/deepest.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deepest/deepest.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/bar.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/bar.js new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/foo.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/foo.js new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js new file mode 100644 index 000000000..9b55b6b93 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js @@ -0,0 +1,486 @@ +'use strict'; + +var path = require('path'); + +var globule = require('../lib/globule.js'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports['match'] = { + 'empty set': function(test) { + test.expect(6); + // Should return empty set if a required argument is missing or an empty set. + test.deepEqual(globule.match(null, 'foo.js'), [], 'should return empty set.'); + test.deepEqual(globule.match('*.js', null), [], 'should return empty set.'); + test.deepEqual(globule.match([], 'foo.js'), [], 'should return empty set.'); + test.deepEqual(globule.match('*.js', []), [], 'should return empty set.'); + test.deepEqual(globule.match(null, ['foo.js']), [], 'should return empty set.'); + test.deepEqual(globule.match(['*.js'], null), [], 'should return empty set.'); + test.done(); + }, + 'basic matching': function(test) { + test.expect(6); + test.deepEqual(globule.match('*.js', 'foo.js'), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match('*.js', ['foo.js']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar.css']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], 'foo.js'), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js', 'bar.css']), ['foo.js', 'bar.css'], 'should match correctly.'); + test.done(); + }, + 'no matches': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', 'foo.css'), [], 'should fail to match.'); + test.deepEqual(globule.match('*.js', ['foo.css', 'bar.css']), [], 'should fail to match.'); + test.done(); + }, + 'unique': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.'); + test.deepEqual(globule.match(['*.js', '*.*'], ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.'); + test.done(); + }, + 'flatten': function(test) { + test.expect(1); + test.deepEqual(globule.match([['*.js', '*.css'], ['*.*', '*.js']], ['foo.js', 'bar.css']), + ['foo.js', 'bar.css'], + 'should process nested pattern arrays correctly.'); + test.done(); + }, + 'exclusion': function(test) { + test.expect(5); + test.deepEqual(globule.match(['!*.js'], ['foo.js', 'bar.js']), [], 'solitary exclusion should match nothing'); + test.deepEqual(globule.match(['*.js', '!*.js'], ['foo.js', 'bar.js']), [], 'exclusion should cancel match'); + test.deepEqual(globule.match(['*.js', '!f*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js'], + 'partial exclusion should partially cancel match'); + test.deepEqual(globule.match(['*.js', '!*.js', 'b*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js'], + 'inclusion / exclusion order matters'); + test.deepEqual(globule.match(['*.js', '!f*.js', '*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js', 'foo.js'], + 'inclusion / exclusion order matters'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js'], {matchBase: true}), + ['foo.js', 'baz/xyz.js'], + 'should matchBase (minimatch) when specified.'); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js']), + ['foo.js'], + 'should not matchBase (minimatch) by default.'); + test.done(); + }, +}; + +exports['isMatch'] = { + 'basic matching': function(test) { + test.expect(6); + test.ok(globule.isMatch('*.js', 'foo.js'), 'should match correctly.'); + test.ok(globule.isMatch('*.js', ['foo.js']), 'should match correctly.'); + test.ok(globule.isMatch('*.js', ['foo.js', 'bar.css']), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], 'foo.js'), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js']), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js', 'bar.css']), 'should match correctly.'); + test.done(); + }, + 'no matches': function(test) { + test.expect(6); + test.ok(!globule.isMatch('*.js', 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', ['foo.css', 'bar.css']), 'should fail to match.'); + test.ok(!globule.isMatch(null, 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', null), 'should fail to match.'); + test.ok(!globule.isMatch([], 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', []), 'should fail to match.'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(2); + test.ok(globule.isMatch('*.js', ['baz/xyz.js'], {matchBase: true}), 'should matchBase (minimatch) when specified.'); + test.ok(!globule.isMatch('*.js', ['baz/xyz.js']), 'should not matchBase (minimatch) by default.'); + test.done(); + }, +}; + +exports['find'] = { + setUp: function(done) { + this.cwd = process.cwd(); + process.chdir('test/fixtures/expand'); + done(); + }, + tearDown: function(done) { + process.chdir(this.cwd); + done(); + }, + 'basic matching': function(test) { + test.expect(5); + test.deepEqual(globule.find('**/*.js'), ['js/bar.js', 'js/foo.js'], 'single pattern argument should match.'); + test.deepEqual(globule.find('**/*.js', '**/*.css'), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'multiple pattern arguments should match.'); + test.deepEqual(globule.find(['**/*.js', '**/*.css']), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'array of patterns should match.'); + test.deepEqual(globule.find([['**/*.js'], [['**/*.css', 'js/*.js']]]), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'array of arrays of patterns should be flattened.'); + test.deepEqual(globule.find('*.xyz'), [], 'bad pattern should fail to match.'); + test.done(); + }, + 'unique': function(test) { + test.expect(4); + test.deepEqual(globule.find('**/*.js', 'js/*.js'), + ['js/bar.js', 'js/foo.js'], + 'file list should be uniqed.'); + test.deepEqual(globule.find('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js', + 'css/baz.css', 'css/qux.css'], + 'file list should be uniqed.'); + test.deepEqual(globule.find('js', 'js/'), + ['js', 'js/'], + 'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.'); + test.deepEqual(globule.find('js', 'js/', {mark: true}), + ['js/'], + 'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.'); + test.done(); + }, + 'file order': function(test) { + test.expect(5); + var actual = globule.find('**/*.{js,css}'); + var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js']; + test.deepEqual(actual, expected, 'should select 4 files in this order, by default.'); + + actual = globule.find('js/foo.js', 'js/bar.js', '**/*.{js,css}'); + expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css']; + test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.'); + + actual = globule.find('js/bar.js', 'js/foo.js', '**/*.{js,css}'); + expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css']; + test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.'); + + actual = globule.find('**/*.{js,css}', '!css/qux.css', 'css/qux.css'); + expected = ['css/baz.css', 'js/bar.js', 'js/foo.js', 'css/qux.css']; + test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.'); + + actual = globule.find('js/foo.js', '**/*.{js,css}', '!css/qux.css', 'css/qux.css'); + expected = ['js/foo.js', 'css/baz.css', 'js/bar.js', 'css/qux.css']; + test.deepEqual(actual, expected, 'should be able to combine specified-up-front and excluded/added-at-end.'); + test.done(); + }, + 'exclusion': function(test) { + test.expect(8); + test.deepEqual(globule.find(['!js/*.js']), [], 'solitary exclusion should match nothing'); + test.deepEqual(globule.find(['js/bar.js','!js/bar.js']), [], 'exclusion should negate match'); + test.deepEqual(globule.find(['**/*.js', '!js/foo.js']), + ['js/bar.js'], + 'should omit single file from matched set'); + test.deepEqual(globule.find(['!js/foo.js', '**/*.js']), + ['js/bar.js', 'js/foo.js'], + 'inclusion / exclusion order matters'); + test.deepEqual(globule.find(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']), + ['js/foo.js','css/qux.css'], + 'multiple exclusions should be removed from the set'); + test.deepEqual(globule.find(['**/*.js', '**/*.css', '!**/*.css']), + ['js/bar.js', 'js/foo.js'], + 'excluded wildcards should be removed from the matched set'); + test.deepEqual(globule.find(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']), + ['js/foo.js', 'css/qux.css'], + 'different pattern for exclusion should still work'); + test.deepEqual(globule.find(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']), + ['js/foo.js', 'css/baz.css', 'css/qux.css'], + 'inclusion / exclusion order matters'); + test.done(); + }, + 'options.mark': function(test) { + test.expect(4); + test.deepEqual(globule.find('**d*/**'), [ + 'deep', + 'deep/deep.txt', + 'deep/deeper', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest', + 'deep/deeper/deepest/deepest.txt'], 'should match files and directories.'); + test.deepEqual(globule.find('**d*/**/'), [ + 'deep/', + 'deep/deeper/', + 'deep/deeper/deepest/'], 'trailing / in pattern should match directories only, matches end in /.'); + test.deepEqual(globule.find('**d*/**', {mark: true}), [ + 'deep/', + 'deep/deep.txt', + 'deep/deeper/', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest/', + 'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.'); + test.deepEqual(globule.find('**d*/**/', {mark: true}), [ + 'deep/', + 'deep/deeper/', + 'deep/deeper/deepest/'], 'the minimatch "mark" option should not remove trailing / from matched paths.'); + test.done(); + }, + 'options.filter': function(test) { + test.expect(5); + test.deepEqual(globule.find('**d*/**', {filter: 'isFile'}), [ + 'deep/deep.txt', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest/deepest.txt' + ], 'should match files only.'); + test.deepEqual(globule.find('**d*/**', {filter: 'isDirectory'}), [ + 'deep', + 'deep/deeper', + 'deep/deeper/deepest' + ], 'should match directories only.'); + test.deepEqual(globule.find('**', { + arbitraryProp: /deepest/, + filter: function(filepath, options) { + return options.arbitraryProp.test(filepath); + } + }), [ + 'deep/deeper/deepest', + 'deep/deeper/deepest/deepest.txt', + ], 'should filter arbitrarily.'); + test.deepEqual(globule.find('js', 'css', {filter: 'isFile'}), [], 'should fail to match.'); + test.deepEqual(globule.find('**/*.js', {filter: 'isDirectory'}), [], 'should fail to match.'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(3); + test.deepEqual(globule.find('*.js'), [], 'should not matchBase (minimatch) by default.'); + test.deepEqual(globule.find('*.js', {matchBase: true}), + ['js/bar.js', 'js/foo.js'], + 'matchBase option should be passed through to minimatch.'); + test.deepEqual(globule.find('*.js', '*.css', {matchBase: true}), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'matchBase option should be passed through to minimatch.'); + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(5); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'should find paths matching pattern relative to srcBase.'); + test.deepEqual(globule.find(['**/deep*.txt'], {cwd: 'deep'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'cwd and srcBase should do the same thing.'); + test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isFile'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'srcBase should not prevent filtering.'); + test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isDirectory'}), + ['deeper', 'deeper/deepest'], + 'srcBase should not prevent filtering.'); + test.deepEqual(globule.find(['**/deep*.txt', '!**/deeper**'], {srcBase: 'deep'}), + ['deep.txt', 'deeper/deepest/deepest.txt'], + 'srcBase should not prevent exclusions.'); + test.done(); + }, + 'options.prefixBase': function(test) { + test.expect(2); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: false}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'should not prefix srcBase to returned paths.'); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: true}), + ['deep/deep.txt', 'deep/deeper/deeper.txt', 'deep/deeper/deepest/deepest.txt'], + 'should prefix srcBase to returned paths.'); + test.done(); + }, + 'options.nonull': function(test) { + test.expect(3); + test.deepEqual(globule.find(['*omg*'], {nonull: true}), + ['*omg*'], + 'non-matching patterns should be returned in result set.'); + test.deepEqual(globule.find(['js/a*', 'js/b*', 'js/c*'], {nonull: true}), + ['js/a*', 'js/bar.js', 'js/c*'], + 'non-matching patterns should be returned in result set.'); + test.deepEqual(globule.find(['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], {nonull: true}), + ['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], + 'non-matching filenames should be returned in result set.'); + test.done(); + }, +}; + +exports['mapping'] = { + 'basic mapping': function(test) { + test.expect(1); + + var actual = globule.mapping(['a.txt', 'b.txt', 'c.txt']); + var expected = [ + {dest: 'a.txt', src: ['a.txt']}, + {dest: 'b.txt', src: ['b.txt']}, + {dest: 'c.txt', src: ['c.txt']}, + ]; + test.deepEqual(actual, expected, 'default options should create same-to-same src-dest mappings.'); + + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(2); + var actual, expected; + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo'}); + expected = [ + {dest: 'a.txt', src: ['foo/a.txt']}, + {dest: 'bar/b.txt', src: ['foo/bar/b.txt']}, + {dest: 'bar/baz/c.txt', src: ['foo/bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (no trailing /).'); + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo/'}); + test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (trailing /).'); + + test.done(); + }, + 'options.destBase': function(test) { + test.expect(2); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest'}); + expected = [ + {dest: 'dest/a.txt', src: ['a.txt']}, + {dest: 'dest/bar/b.txt', src: ['bar/b.txt']}, + {dest: 'dest/bar/baz/c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (no trailing /).'); + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest/'}); + test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (trailing /).'); + + test.done(); + }, + 'options.flatten': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {flatten: true}); + expected = [ + {dest: 'a.txt', src: ['a.txt']}, + {dest: 'b.txt', src: ['bar/b.txt']}, + {dest: 'c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'flatten should remove all src path parts from dest.'); + + test.done(); + }, + 'options.flatten + options.destBase': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest', flatten: true}); + expected = [ + {dest: 'dest/a.txt', src: ['a.txt']}, + {dest: 'dest/b.txt', src: ['bar/b.txt']}, + {dest: 'dest/c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'flatten and destBase should work together.'); + + test.done(); + }, + 'options.ext': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['x/a.js', 'x.y/b.min.js', 'x.y/z.z/c'], {ext: '.foo'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.foo', src: ['x.y/b.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'by default, ext should replace everything after the first dot in the filename.'); + + test.done(); + }, + 'options.extDot': function(test) { + test.expect(2); + var actual, expected; + + actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'first'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.foo', src: ['x.y/b.bbb.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.'); + + actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'last'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.bbb.min.foo', src: ['x.y/b.bbb.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.'); + + test.done(); + }, + 'options.rename': function(test) { + test.expect(1); + var actual, expected; + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], { + arbitraryProp: 'FOO', + rename: function(dest, options) { + return path.join(options.arbitraryProp, dest.toUpperCase()); + } + }); + expected = [ + {dest: 'FOO/A.TXT', src: ['a.txt']}, + {dest: 'FOO/BAR/B.TXT', src: ['bar/b.txt']}, + {dest: 'FOO/BAR/BAZ/C.TXT', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'allow arbitrary renaming of files.'); + + test.done(); + }, +}; + +exports['findMapping'] = { + setUp: function(done) { + this.cwd = process.cwd(); + process.chdir('test/fixtures'); + done(); + }, + tearDown: function(done) { + process.chdir(this.cwd); + done(); + }, + 'basic matching': function(test) { + test.expect(2); + + var actual = globule.findMapping(['expand/**/*.txt']); + var expected = [ + {dest: 'expand/deep/deep.txt', src: ['expand/deep/deep.txt']}, + {dest: 'expand/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']}, + {dest: 'expand/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']}, + ]; + test.deepEqual(actual, expected, 'default options'); + + expected = globule.mapping(globule.find(['expand/**/*.txt'])); + test.deepEqual(actual, expected, 'this is what it\'s doing under the hood, anwyays.'); + + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(1); + var actual = globule.findMapping(['**/*.txt'], {destBase: 'dest', srcBase: 'expand/deep'}); + var expected = [ + {dest: 'dest/deep.txt', src: ['expand/deep/deep.txt']}, + {dest: 'dest/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']}, + {dest: 'dest/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']}, + ]; + test.deepEqual(actual, expected, 'srcBase should be stripped from front of destPath, pre-destBase+destPath join'); + test.done(); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/package.json new file mode 100644 index 000000000..f1e2c21de --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/package.json @@ -0,0 +1,92 @@ +{ + "name": "gaze", + "description": "A globbing fs.watch wrapper built from the best parts of other fine watch libs.", + "version": "0.4.3", + "homepage": "https://github.com/shama/gaze", + "author": { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/shama/gaze.git" + }, + "bugs": { + "url": "https://github.com/shama/gaze/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/shama/gaze/blob/master/LICENSE-MIT" + } + ], + "main": "lib/gaze", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt nodeunit -v" + }, + "dependencies": { + "globule": "~0.1.0" + }, + "devDependencies": { + "grunt": "~0.4.1", + "grunt-contrib-nodeunit": "~0.2.0", + "grunt-contrib-jshint": "~0.6.0", + "grunt-benchmark": "~0.2.0" + }, + "keywords": [ + "watch", + "glob" + ], + "contributors": [ + { + "name": "Kyle Robinson Young", + "url": "http://dontkry.com" + }, + { + "name": "Sam Day", + "url": "http://sam.is-super-awesome.com" + }, + { + "name": "Roarke Gaskill", + "url": "http://starkinvestments.com" + }, + { + "name": "Lance Pollard", + "url": "http://lancepollard.com/" + }, + { + "name": "Daniel Fagnan", + "url": "http://hydrocodedesign.com/" + }, + { + "name": "Jonas", + "url": "http://jpommerening.github.io/" + }, + { + "name": "Chris Chua", + "url": "http://sirh.cc/" + }, + { + "name": "Kael Zhang", + "url": "http://kael.me" + }, + { + "name": "Krasimir Tsonev", + "url": "http://krasimirtsonev.com/blog" + }, + { + "name": "brett-shwom" + } + ], + "readme": "# gaze [![Build Status](https://secure.travis-ci.org/shama/gaze.png?branch=master)](http://travis-ci.org/shama/gaze)\n\nA globbing fs.watch wrapper built from the best parts of other fine watch libs. \nCompatible with Node.js 0.10/0.8, Windows, OSX and Linux.\n\n![gaze](http://dontkry.com/images/repos/gaze.png)\n\n## Usage\nInstall the module with: `npm install gaze` or place into your `package.json`\nand run `npm install`.\n\n```javascript\nvar gaze = require('gaze');\n\n// Watch all .js files/dirs in process.cwd()\ngaze('**/*.js', function(err, watcher) {\n // Files have all started watching\n // watcher === this\n\n // Get all watched files\n console.log(this.watched());\n\n // On file changed\n this.on('changed', function(filepath) {\n console.log(filepath + ' was changed');\n });\n\n // On file added\n this.on('added', function(filepath) {\n console.log(filepath + ' was added');\n });\n\n // On file deleted\n this.on('deleted', function(filepath) {\n console.log(filepath + ' was deleted');\n });\n\n // On changed/added/deleted\n this.on('all', function(event, filepath) {\n console.log(filepath + ' was ' + event);\n });\n\n // Get watched files with relative paths\n console.log(this.relative());\n});\n\n// Also accepts an array of patterns\ngaze(['stylesheets/*.css', 'images/**/*.png'], function() {\n // Add more patterns later to be watched\n this.add(['js/*.js']);\n});\n```\n\n### Alternate Interface\n\n```javascript\nvar Gaze = require('gaze').Gaze;\n\nvar gaze = new Gaze('**/*');\n\n// Files have all started watching\ngaze.on('ready', function(watcher) { });\n\n// A file has been added/changed/deleted has occurred\ngaze.on('all', function(event, filepath) { });\n```\n\n### Errors\n\n```javascript\ngaze('**/*', function() {\n this.on('error', function(err) {\n // Handle error here\n });\n});\n```\n\n### Minimatch / Glob\n\nSee [isaacs's minimatch](https://github.com/isaacs/minimatch) for more\ninformation on glob patterns.\n\n## Documentation\n\n### gaze(patterns, [options], callback)\n\n* `patterns` {String|Array} File patterns to be matched\n* `options` {Object}\n* `callback` {Function}\n * `err` {Error | null}\n * `watcher` {Object} Instance of the Gaze watcher\n\n### Class: gaze.Gaze\n\nCreate a Gaze object by instanting the `gaze.Gaze` class.\n\n```javascript\nvar Gaze = require('gaze').Gaze;\nvar gaze = new Gaze(pattern, options, callback);\n```\n\n#### Properties\n\n* `options` The options object passed in.\n * `interval` {integer} Interval to pass to fs.watchFile\n * `debounceDelay` {integer} Delay for events called in succession for the same\n file/event\n\n#### Events\n\n* `ready(watcher)` When files have been globbed and watching has begun.\n* `all(event, filepath)` When an `added`, `changed` or `deleted` event occurs.\n* `added(filepath)` When a file has been added to a watch directory.\n* `changed(filepath)` When a file has been changed.\n* `deleted(filepath)` When a file has been deleted.\n* `renamed(newPath, oldPath)` When a file has been renamed.\n* `end()` When the watcher is closed and watches have been removed.\n* `error(err)` When an error occurs.\n\n#### Methods\n\n* `emit(event, [...])` Wrapper for the EventEmitter.emit.\n `added`|`changed`|`deleted` events will also trigger the `all` event.\n* `close()` Unwatch all files and reset the watch instance.\n* `add(patterns, callback)` Adds file(s) patterns to be watched.\n* `remove(filepath)` removes a file or directory from being watched. Does not\n recurse directories.\n* `watched()` Returns the currently watched files.\n* `relative([dir, unixify])` Returns the currently watched files with relative paths.\n * `dir` {string} Only return relative files for this directory.\n * `unixify` {boolean} Return paths with `/` instead of `\\\\` if on Windows.\n\n## FAQs\n\n### Why Another `fs.watch` Wrapper?\nI liked parts of other `fs.watch` wrappers but none had all the features I\nneeded. This lib combines the features I needed from other fine watch libs:\nSpeedy data behavior from\n[paulmillr's chokidar](https://github.com/paulmillr/chokidar), API interface\nfrom [mikeal's watch](https://github.com/mikeal/watch) and file globbing using\n[isaacs's glob](https://github.com/isaacs/node-glob) which is also used by\n[cowboy's Grunt](https://github.com/gruntjs/grunt).\n\n### How do I fix the error `EMFILE: Too many opened files.`?\nThis is because of your system's max opened file limit. For OSX the default is\nvery low (256). Increase your limit temporarily with `ulimit -n 10480`, the\nnumber being the new max limit.\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style.\nAdd unit tests for any new or changed functionality. Lint and test your code\nusing [grunt](http://gruntjs.com/).\n\n## Release History\n* 0.4.3 - Track file additions in newly created folders (@brett-shwom).\n* 0.4.2 - Fix .remove() method to remove a single file in a directory (@kaelzhang). Fixing Cannot call method 'call' of undefined (@krasimir). Track new file additions within folders (@brett-shwom).\n* 0.4.1 - Fix watchDir not respecting close in race condition (@chrisirhc).\n* 0.4.0 - Drop support for node v0.6. Use globule for file matching. Avoid node v0.10 path.resolve/join errors. Register new files when added to non-existent folder. Multiple instances can now poll the same files (@jpommerening).\n* 0.3.4 - Code clean up. Fix path must be strings errors (@groner). Fix incorrect added events (@groner).\n* 0.3.3 - Fix for multiple patterns with negate.\n* 0.3.2 - Emit `end` before removeAllListeners.\n* 0.3.1 - Fix added events within subfolder patterns.\n* 0.3.0 - Handle safewrite events, `forceWatchMethod` option removed, bug fixes and watch optimizations (@rgaskill).\n* 0.2.2 - Fix issue where subsequent add calls dont get watched (@samcday). removeAllListeners on close.\n* 0.2.1 - Fix issue with invalid `added` events in current working dir.\n* 0.2.0 - Support and mark folders with `path.sep`. Add `forceWatchMethod` option. Support `renamed` events.\n* 0.1.6 - Recognize the `cwd` option properly\n* 0.1.5 - Catch too many open file errors\n* 0.1.4 - Really fix the race condition with 2 watches\n* 0.1.3 - Fix race condition with 2 watches\n* 0.1.2 - Read triggering changed event fix\n* 0.1.1 - Minor fixes\n* 0.1.0 - Initial release\n\n## License\nCopyright (c) 2013 Kyle Robinson Young \nLicensed under the MIT license.\n", + "readmeFilename": "README.md", + "_id": "gaze@0.4.3", + "dist": { + "shasum": "619c938ef9ae391ef8ff8598264a656910c9178f" + }, + "_from": "gaze@~0.4.0", + "_resolved": "https://registry.npmjs.org/gaze/-/gaze-0.4.3.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js new file mode 100644 index 000000000..cfb1e89bf --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js @@ -0,0 +1,69 @@ +'use strict'; + +var Gaze = require('../lib/gaze.js').Gaze; +var path = require('path'); +var fs = require('fs'); +var helper = require('./helper'); + +var fixtures = path.resolve(__dirname, 'fixtures'); +var sortobj = helper.sortobj; + +exports.add = { + setUp: function(done) { + process.chdir(fixtures); + done(); + }, + addToWatched: function(test) { + test.expect(1); + var files = [ + 'Project (LO)/', + 'Project (LO)/one.js', + 'nested/', + 'nested/one.js', + 'nested/three.js', + 'nested/sub/', + 'nested/sub/two.js', + 'one.js', + ]; + var expected = { + 'Project (LO)/': ['one.js'], + '.': ['Project (LO)/', 'nested/', 'one.js', 'sub/'], + 'nested/': ['sub/', 'sub2/', 'one.js', 'three.js'], + 'nested/sub/': ['two.js'], + }; + var gaze = new Gaze('addnothingtowatch'); + gaze._addToWatched(files); + var result = gaze.relative(null, true); + test.deepEqual(sortobj(result), sortobj(expected)); + test.done(); + }, + addLater: function(test) { + test.expect(3); + new Gaze('sub/one.js', function(err, watcher) { + test.deepEqual(watcher.relative('sub'), ['one.js']); + watcher.add('sub/*.js', function() { + test.deepEqual(watcher.relative('sub'), ['one.js', 'two.js']); + watcher.on('changed', function(filepath) { + test.equal('two.js', path.basename(filepath)); + watcher.close(); + test.done(); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'two.js'), 'var two = true;'); + }); + }); + }, + addNoCallback: function(test) { + test.expect(1); + new Gaze('sub/one.js', function(err, watcher) { + this.add('sub/two.js'); + this.on('changed', function(filepath) { + test.equal('two.js', path.basename(filepath)); + watcher.close(); + test.done(); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'two.js'), 'var two = true;'); + }, 500); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js new file mode 100644 index 000000000..42d258e1f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js @@ -0,0 +1,38 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); + +exports.api = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + done(); + }, + newGaze: function(test) { + test.expect(2); + new gaze.Gaze('**/*', {}, function() { + var result = this.relative(null, true); + test.deepEqual(result['.'], ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + func: function(test) { + test.expect(1); + var g = gaze('**/*', function(err, watcher) { + test.deepEqual(watcher.relative('sub', true), ['one.js', 'two.js']); + g.close(); + test.done(); + }); + }, + ready: function(test) { + test.expect(1); + var g = new gaze.Gaze('**/*'); + g.on('ready', function(watcher) { + test.deepEqual(watcher.relative('sub', true), ['one.js', 'two.js']); + this.close(); + test.done(); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js new file mode 100644 index 000000000..6e969376c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js @@ -0,0 +1,27 @@ +'use strict'; + +var path = require('path'); +var fs = require('fs'); + +var timeout = +process.argv[2]; +if (!timeout || isNaN(timeout)) { + throw 'No specified timeout'; +} +setTimeout(function () { + process.exit(); +}, timeout); + +var pathArg = process.argv.slice(3); +if (!pathArg.length) { + throw 'No path arguments'; +} +var filepath = path.resolve.apply(path, [ __dirname ].concat(pathArg)); + +function writeToFile() { + setTimeout(function () { + fs.writeFile(filepath, ''); + return writeToFile(); + }, 0); +} + +writeToFile(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js new file mode 100644 index 000000000..fefeeeaa8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js new file mode 100644 index 000000000..fefeeeaa8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js new file mode 100644 index 000000000..24ad8a36f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js new file mode 100644 index 000000000..24ad8a36f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js new file mode 100644 index 000000000..339295619 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js @@ -0,0 +1 @@ +var three = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js new file mode 100644 index 000000000..7a4b5f6af --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js @@ -0,0 +1 @@ +var test = true; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js new file mode 100644 index 000000000..fefeeeaa8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js new file mode 100644 index 000000000..24ad8a36f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js new file mode 100644 index 000000000..5452e3e73 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js @@ -0,0 +1,21 @@ +'use strict'; + +var helper = module.exports = {}; + +helper.sortobj = function sortobj(obj) { + if (Array.isArray(obj)) { + obj.sort(); + return obj; + } + var out = Object.create(null); + var keys = Object.keys(obj); + keys.sort(); + keys.forEach(function(key) { + var val = obj[key]; + if (Array.isArray(val)) { + val.sort(); + } + out[key] = val; + }); + return out; +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js new file mode 100644 index 000000000..8261f2b99 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js @@ -0,0 +1,95 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var helper = require('./helper'); + +var fixtures = path.resolve(__dirname, 'fixtures'); +var sortobj = helper.sortobj; + +function cleanUp(done) { + [ + 'newfolder', + ].forEach(function(d) { + var p = path.join(fixtures, d); + if (grunt.file.exists(p)) { + grunt.file.delete(p); + } + }); + done(); +} + +exports.matching = { + setUp: function(done) { + process.chdir(fixtures); + cleanUp(done); + }, + tearDown: cleanUp, + globAll: function(test) { + test.expect(2); + gaze('**/*', function() { + var result = this.relative(null, true); + test.deepEqual(result['.'], ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + relativeDir: function(test) { + test.expect(1); + gaze('**/*', function() { + test.deepEqual(this.relative('sub', true), ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + globArray: function(test) { + test.expect(2); + gaze(['*.js', 'sub/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(sortobj(result['.']), sortobj(['one.js', 'Project (LO)/', 'nested/', 'sub/'])); + test.deepEqual(sortobj(result['sub/']), sortobj(['one.js', 'two.js'])); + this.close(); + test.done(); + }); + }, + globArrayDot: function(test) { + test.expect(1); + gaze(['./sub/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + oddName: function(test) { + test.expect(1); + gaze(['Project (LO)/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(result['Project (LO)/'], ['one.js']); + this.close(); + test.done(); + }); + }, + addedLater: function(test) { + test.expect(2); + var times = 0; + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + times++; + var result = watcher.relative(null, true); + test.deepEqual(result['newfolder/'], ['added.js']); + if (times > 1) { watcher.close(); } + }); + grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); + setTimeout(function() { + grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); + }, 1000); + watcher.on('end', function() { + // TODO: Figure out why this test is finicky leaking it's newfolder into the other tests + setTimeout(test.done, 2000); + }); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js new file mode 100644 index 000000000..46b94e40b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js @@ -0,0 +1,42 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'added.js', + 'nested/added.js', + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.patterns = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + negate: function(test) { + test.expect(1); + gaze(['**/*.js', '!nested/**/*.js'], function(err, watcher) { + watcher.on('added', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('added.js'), expected); + watcher.close(); + }); + // dont add + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'nested', 'added.js'), 'var added = true;'); + setTimeout(function() { + // should add + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'added.js'), 'var added = true;'); + }, 1000); + watcher.on('end', test.done); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js new file mode 100644 index 000000000..492d8e569 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js @@ -0,0 +1,28 @@ +'use strict'; + +var Gaze = require('../lib/gaze.js').Gaze; +var path = require('path'); + +exports.relative = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + done(); + }, + relative: function(test) { + test.expect(1); + var files = [ + 'Project (LO)/', + 'Project (LO)/one.js', + 'nested/', + 'nested/one.js', + 'nested/three.js', + 'nested/sub/', + 'nested/sub/two.js', + 'one.js' + ]; + var gaze = new Gaze('addnothingtowatch'); + gaze._addToWatched(files); + test.deepEqual(gaze.relative('.', true), ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.done(); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js new file mode 100644 index 000000000..5d2d496ec --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js @@ -0,0 +1,40 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'sub/rename.js', + 'sub/renamed.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.watch = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + rename: function(test) { + test.expect(2); + var oldPath = path.join(__dirname, 'fixtures', 'sub', 'rename.js'); + var newPath = path.join(__dirname, 'fixtures', 'sub', 'renamed.js'); + fs.writeFileSync(oldPath, 'var rename = true;'); + gaze('**/*', function(err, watcher) { + watcher.on('renamed', function(newFile, oldFile) { + test.equal(newFile, newPath); + test.equal(oldFile, oldPath); + watcher.close(); + test.done(); + }); + fs.renameSync(oldPath, newPath); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js new file mode 100644 index 000000000..ac76b9386 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js @@ -0,0 +1,58 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'safewrite.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.safewrite = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + safewrite: function(test) { + test.expect(4); + + var times = 0; + var file = path.resolve(__dirname, 'fixtures', 'safewrite.js'); + var backup = path.resolve(__dirname, 'fixtures', 'safewrite.ext~'); + fs.writeFileSync(file, 'var safe = true;'); + + function simSafewrite() { + fs.writeFileSync(backup, fs.readFileSync(file)); + fs.unlinkSync(file); + fs.renameSync(backup, file); + times++; + } + + gaze('**/*', function() { + this.on('all', function(action, filepath) { + test.equal(action, 'changed'); + test.equal(path.basename(filepath), 'safewrite.js'); + + if (times < 2) { + setTimeout(simSafewrite, 1000); + } else { + this.close(); + test.done(); + } + }); + + setTimeout(function() { + simSafewrite(); + }, 1000); + + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js new file mode 100644 index 000000000..e524692da --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js @@ -0,0 +1,84 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var fs = require('fs'); +var cp = require('child_process'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'nested/sub/poller.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.watch_race = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + initWatchDirOnClose: function(test) { + var times = 5, + TIMEOUT = 5000, + firedWhenClosed = 0, + watchers = [], + watcherIdxes = [], + polled_file = ['fixtures', 'nested', 'sub', 'poller.js'], + expected_path = path.join.apply(path, polled_file.slice(1)); + test.expect(times); + for (var i = times; i--;) { + watcherIdxes.unshift(i); + } + // Create the file so that it can be watched + fs.writeFileSync(path.resolve.apply(path, [__dirname].concat(polled_file)), ''); + // Create a poller that keeps making changes to the file until timeout + var child_poller = cp.fork( + '../file_poller.js', + [times * TIMEOUT].concat(polled_file) + ); + grunt.util.async.forEachSeries(watcherIdxes, function(idx, next) { + var watcher = new gaze.Gaze('**/poller.js', function(err, watcher) { + var timeout = setTimeout(function () { + test.ok(false, 'watcher ' + idx + ' did not fire event on polled file.'); + watcher.close(); + }, TIMEOUT); + watcher.on('all', function (status, filepath) { + if (!filepath) { return; } + var expected = path.relative(process.cwd(), filepath); + test.equal(expected_path, expected, 'watcher ' + idx + + ' emitted unexpected event.'); + clearTimeout(timeout); + watcher.close(); + }); + watcher.on('end', function () { + // After watcher is closed and all event listeners have been removed, + // re-add a listener to see if anything is going on on this watcher. + process.nextTick(function () { + watcher.once('added', function () { + test.ok(false, 'watcher ' + idx + ' should not fire added' + + ' event on polled file after being closed.'); + }); + }); + next(); + }); + }); + watchers.push(watcher); + }, function () { + child_poller.kill(); + watchers.forEach(function (watcher) { + try { + watcher.close(); + } catch (e) { + // Ignore if this fails + } + }); + test.done(); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js new file mode 100644 index 000000000..0f3d368c5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js @@ -0,0 +1,314 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'sub/tmp.js', + 'sub/tmp', + 'sub/renamed.js', + 'added.js', + 'nested/added.js', + 'nested/.tmp', + 'nested/sub/added.js', + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + + grunt.file.delete(path.resolve(__dirname, 'fixtures', 'new_dir')); + + done(); +} + +exports.watch = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + remove: function(test) { + test.expect(2); + gaze('**/*', function() { + this.remove(path.resolve(__dirname, 'fixtures', 'sub', 'two.js')); + this.remove(path.resolve(__dirname, 'fixtures')); + var result = this.relative(null, true); + test.deepEqual(result['sub/'], ['one.js']); + test.notDeepEqual(result['.'], ['one.js']); + this.close(); + test.done(); + }); + }, + changed: function(test) { + test.expect(1); + gaze('**/*', function(err, watcher) { + watcher.on('changed', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'one.js'), expected); + watcher.close(); + }); + this.on('added', function() { test.ok(false, 'added event should not have emitted.'); }); + this.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + watcher.on('end', test.done); + }); + }, + added: function(test) { + test.expect(1); + gaze('**/*', function(err, watcher) { + watcher.on('added', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'tmp.js'), expected); + watcher.close(); + }); + this.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + this.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp.js'), 'var tmp = true;'); + watcher.on('end', test.done); + }); + }, + dontAddUnmatchedFiles: function(test) { + test.expect(2); + gaze('**/*.js', function(err, watcher) { + setTimeout(function() { + test.ok(true, 'Ended without adding a file.'); + watcher.close(); + }, 1000); + this.on('added', function(filepath) { + test.equal(path.relative(process.cwd(), filepath), path.join('sub', 'tmp.js')); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp'), 'Dont add me!'); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp.js'), 'add me!'); + watcher.on('end', test.done); + }); + }, + dontAddMatchedDirectoriesThatArentReallyAdded: function(test) { + // This is a regression test for a bug I ran into where a matching directory would be reported + // added when a non-matching file was created along side it. This only happens if the + // directory name doesn't occur in $PWD. + test.expect(1); + gaze('**/*', function(err, watcher) { + setTimeout(function() { + test.ok(true, 'Ended without adding a file.'); + watcher.close(); + }, 1000); + this.on('added', function(filepath) { + test.notEqual(path.relative(process.cwd(), filepath), path.join('nested', 'sub2')); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'nested', '.tmp'), 'Wake up!'); + watcher.on('end', test.done); + }); + }, + deleted: function(test) { + test.expect(1); + var tmpfile = path.resolve(__dirname, 'fixtures', 'sub', 'deleted.js'); + fs.writeFileSync(tmpfile, 'var tmp = true;'); + gaze('**/*', function(err, watcher) { + watcher.on('deleted', function(filepath) { + test.equal(path.join('sub', 'deleted.js'), path.relative(process.cwd(), filepath)); + watcher.close(); + }); + this.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + this.on('added', function() { test.ok(false, 'added event should not have emitted.'); }); + fs.unlinkSync(tmpfile); + watcher.on('end', test.done); + }); + }, + dontEmitTwice: function(test) { + test.expect(2); + gaze('**/*', function(err, watcher) { + watcher.on('all', function(status, filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'one.js'), expected); + test.equal(status, 'changed'); + fs.readFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js')); + setTimeout(function() { + fs.readFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js')); + }, 1000); + // Give some time to accidentally emit before we close + setTimeout(function() { watcher.close(); }, 5000); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + }, 1000); + watcher.on('end', test.done); + }); + }, + emitTwice: function(test) { + test.expect(2); + var times = 0; + gaze('**/*', function(err, watcher) { + watcher.on('all', function(status, filepath) { + test.equal(status, 'changed'); + times++; + setTimeout(function() { + if (times < 2) { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + } else { + watcher.close(); + } + }, 1000); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + }, 1000); + watcher.on('end', test.done); + }); + }, + nonExistent: function(test) { + test.expect(1); + gaze('non/existent/**/*', function(err, watcher) { + test.ok(true); + test.done(); + }); + }, + differentCWD: function(test) { + test.expect(1); + var cwd = path.resolve(__dirname, 'fixtures', 'sub'); + gaze('two.js', { + cwd: cwd + }, function(err, watcher) { + watcher.on('changed', function(filepath) { + test.deepEqual(this.relative(), {'.':['two.js']}); + watcher.close(); + }); + fs.writeFileSync(path.resolve(cwd, 'two.js'), 'var two = true;'); + watcher.on('end', test.done); + }); + }, + addedEmitInSubFolders: function(test) { + test.expect(4); + var adds = [ + { pattern: '**/*', file: path.resolve(__dirname, 'fixtures', 'nested', 'sub', 'added.js') }, + { pattern: '**/*', file: path.resolve(__dirname, 'fixtures', 'added.js') }, + { pattern: 'nested/**/*', file: path.resolve(__dirname, 'fixtures', 'nested', 'added.js') }, + { pattern: 'nested/sub/*.js', file: path.resolve(__dirname, 'fixtures', 'nested', 'sub', 'added.js') }, + ]; + grunt.util.async.forEachSeries(adds, function(add, next) { + new gaze.Gaze(add.pattern, function(err, watcher) { + watcher.on('added', function(filepath) { + test.equal('added.js', path.basename(filepath)); + fs.unlinkSync(filepath); + watcher.close(); + next(); + }); + watcher.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + watcher.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(add.file, 'var added = true;'); + }); + }, function() { + test.done(); + }); + }, + multipleWatchersSimultaneously: function(test) { + test.expect(2); + var did = 0; + var ready = 0; + var cwd = path.resolve(__dirname, 'fixtures', 'sub'); + var watchers = []; + var timeout = setTimeout(function() { + test.ok(false, "Only " + did + " of " + ready + " watchers fired."); + test.done(); + watchers.forEach(function(watcher) { + watcher.close(); + }); + }, 1000); + + function isReady() { + ready++; + if (ready > 1) { + fs.writeFileSync(path.resolve(cwd, 'one.js'), 'var one = true;'); + } + } + function isDone() { + did++; + if (did > 1) { + clearTimeout(timeout); + watchers.forEach(function(watcher) { + watcher.close(); + }); + test.done(); + } + } + function changed(filepath) { + test.equal(path.join('sub', 'one.js'), path.relative(process.cwd(), filepath)); + isDone(); + } + for (var i = 0; i < 2; i++) { + watchers[i] = new gaze.Gaze('sub/one.js'); + watchers[i].on('changed', changed); + watchers[i].on('ready', isReady); + } + }, + mkdirThenAddFile: function(test) { + test.expect(2); + + var expected = [ + 'new_dir', + 'new_dir/other.js', + ]; + + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + + var expect = expected.shift(); + test.equal(path.relative(process.cwd(), filepath), expect); + + if (expected.length === 1) { + // Ensure the new folder is being watched correctly after initial add + setTimeout(function() { + fs.writeFileSync('new_dir/dontmatch.txt', ''); + setTimeout(function() { + fs.writeFileSync('new_dir/other.js', ''); + }, 1000); + }, 1000); + } + + if (expected.length < 1) { watcher.close(); } + }); + + + fs.mkdirSync('new_dir'); //fs.mkdirSync([folder]) seems to behave differently than grunt.file.write('[folder]/[file]') + + + watcher.on('end', test.done); + }); + }, + mkdirThenAddFileWithGruntFileWrite: function(test) { + test.expect(3); + + var expected = [ + 'new_dir', + 'new_dir/tmp.js', + 'new_dir/other.js', + ]; + + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + + var expect = expected.shift(); + test.equal(path.relative(process.cwd(), filepath), expect); + + if (expected.length === 1) { + // Ensure the new folder is being watched correctly after initial add + setTimeout(function() { + fs.writeFileSync('new_dir/dontmatch.txt', ''); + setTimeout(function() { + fs.writeFileSync('new_dir/other.js', ''); + }, 1000); + }, 1000); + } + + if (expected.length < 1) { watcher.close(); } + }); + + grunt.file.write('new_dir/tmp.js', ''); + + watcher.on('end', test.done); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore new file mode 100644 index 000000000..1e107f52e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore @@ -0,0 +1 @@ +examples diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml new file mode 100644 index 000000000..baa0031d5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr new file mode 100755 index 000000000..26634468f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr @@ -0,0 +1,68 @@ +#!/usr/bin/env node + +var fs = require('fs'); +var path = require('path'); + +// default DEBUG if not set already +process.env.DEBUG = process.env.DEBUG || 'tinylr tinylr:*'; + +var Server = require('..').Server; +var noptify = require('noptify'); + +var program = noptify(process.argv, { program: 'tiny-lr' }) + .version('0.0.1') + .option('port', '-p', 'Port to listen on (default: 35729)', Number) + .option('pid', 'Path to the generated PID file (default: ./tiny-lr.pid)', String); + +var opts = program.parse(); +opts.port = opts.port || 35729; +opts.pid = opts.pid || path.resolve('tiny-lr.pid'); + +// if it was required, don't start the server and expose the Server object. +if (module.parent) { + module.exports = Server; + return; +} + +// Server + +// Thanks to @FGRibreau for his very simple and very handy gist: +// https://gist.github.com/1846952 + +process.title = 'tiny-lr'; + +process.on('exit', function() { + console.log('... Closing server ...'); + console.log('... Removing pid file (%s) ...', opts.pid); + fs.unlinkSync(opts.pid); +}); + +process.on('SIGTERM', function() { + return process.exit(0); +}); + +process.on('SIGINT', function() { + return process.exit(0); +}); + + +var srv = new Server(opts); + +srv.on('close', function() { + process.nextTick(function() { + process.exit(); + }); +}); + +console.log(); +srv.listen(opts.port, function(err) { + fs.writeFile(opts.pid, process.pid, function(err) { + if(err) { + console.log('... Cannot write pid file: %s', opts.pid); + process.exit(1) + } + + console.log('... Listening on %s (pid: %s) ...', opts.port, process.pid); + console.log('... pid file: %s', opts.pid); + }); +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload new file mode 100755 index 000000000..b0d6c85d0 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload @@ -0,0 +1,13 @@ +#!/usr/bin/env node + +var fs = require('fs'); +var path = require('path'); +var request = require('request'); + +var file = path.join(__dirname, '..', 'lib/public/livereload.js'); +var url = process.argv.slice(2)[0] || 'https://raw.github.com/livereload/livereload-js/master/dist/livereload.js'; + +console.error('Updating livereload.js %s from %s', file, url); +request(url) + .pipe(fs.createWriteStream(file)) + .on('close', console.log.bind(console, 'Done')); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js new file mode 100644 index 000000000..f484d30f2 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js @@ -0,0 +1,81 @@ + +var util = require('util'); +var events = require('events'); +var WebSocket = require('faye-websocket'); + +module.exports = Client; + +function Client(req, socket, head) { + this.ws = new WebSocket(req, socket, head); + this.ws.onmessage = this.message.bind(this); + this.ws.onclose = this.close.bind(this); + this.id = this.uniqueId('ws'); +} + +util.inherits(Client, events.EventEmitter); + +Client.prototype.message = function message(event) { + // console.log('... Incoming %s ...', event.type); + var data = this.data(event); + if(this[data.command]) return this[data.command](data); +}; + +Client.prototype.close = function close(event) { + if(this.ws) { + this.ws.close(); + this.ws = null; + } + + this.emit('end', event); +}; + +// Commands + +Client.prototype.hello = function hello() { + this.send({ + command: 'hello', + protocols: [ + 'http://livereload.com/protocols/official-7' + ], + serverName: 'tiny-lr' + }); +}; + +Client.prototype.info = function info(data) { + this.plugins = data.plugins; + this.url = data.url; +}; + +// Server commands + +Client.prototype.reload = function reload(files) { + files.forEach(function(file) { + console.log('... Reload %s ...', file); + this.send({ + command: 'reload', + path: file, + liveCss: true, + liveJs: true + }); + }, this); +}; + +// Utilities + +Client.prototype.data = function _data(event) { + var data = {}; + try { + data = JSON.parse(event.data); + } catch (e) {} + return data; +}; + +Client.prototype.send = function send(data) { + this.ws.send(JSON.stringify(data)); +}; + +var idCounter = 0; +Client.prototype.uniqueId = function uniqueId(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js new file mode 100644 index 000000000..1420629f3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js @@ -0,0 +1,22 @@ + +var Server = require('./server'); +var Client = require('./client'); + +module.exports = tinylr; +tinylr.Server = Server; +tinylr.Client = Client; + +tinylr.middleware = middleware; + +function tinylr(opts) { + return new Server(opts); +} + +var util = require('util'); + +function middleware(opts) { + var srv = new Server(opts); + return function tinylr(req, res, next) { + srv.handler(req, res, next); + }; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js new file mode 100644 index 000000000..edb280265 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js @@ -0,0 +1,1055 @@ +(function() { +var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {}; + +// customevents +var CustomEvents; +CustomEvents = { + bind: function(element, eventName, handler) { + if (element.addEventListener) { + return element.addEventListener(eventName, handler, false); + } else if (element.attachEvent) { + element[eventName] = 1; + return element.attachEvent('onpropertychange', function(event) { + if (event.propertyName === eventName) { + return handler(); + } + }); + } else { + throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); + } + }, + fire: function(element, eventName) { + var event; + if (element.addEventListener) { + event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + return document.dispatchEvent(event); + } else if (element.attachEvent) { + if (element[eventName]) { + return element[eventName]++; + } + } else { + throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); + } + } +}; +__customevents.bind = CustomEvents.bind; +__customevents.fire = CustomEvents.fire; + +// protocol +var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError; +var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; +}; +__protocol.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; +__protocol.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; +__protocol.ProtocolError = ProtocolError = (function() { + function ProtocolError(reason, data) { + this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; + } + return ProtocolError; +})(); +__protocol.Parser = Parser = (function() { + function Parser(handlers) { + this.handlers = handlers; + this.reset(); + } + Parser.prototype.reset = function() { + return this.protocol = null; + }; + Parser.prototype.process = function(data) { + var command, message, options, _ref; + try { + if (!(this.protocol != null)) { + if (data.match(/^!!ver:([\d.]+)$/)) { + this.protocol = 6; + } else if (message = this._parseMessage(data, ['hello'])) { + if (!message.protocols.length) { + throw new ProtocolError("no protocols specified in handshake message"); + } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { + this.protocol = 7; + } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { + this.protocol = 6; + } else { + throw new ProtocolError("no supported protocols found"); + } + } + return this.handlers.connected(this.protocol); + } else if (this.protocol === 6) { + message = JSON.parse(data); + if (!message.length) { + throw new ProtocolError("protocol 6 messages must be arrays"); + } + command = message[0], options = message[1]; + if (command !== 'refresh') { + throw new ProtocolError("unknown protocol 6 command"); + } + return this.handlers.message({ + command: 'reload', + path: options.path, + liveCSS: (_ref = options.apply_css_live) != null ? _ref : true + }); + } else { + message = this._parseMessage(data, ['reload', 'alert']); + return this.handlers.message(message); + } + } catch (e) { + if (e instanceof ProtocolError) { + return this.handlers.error(e); + } else { + throw e; + } + } + }; + Parser.prototype._parseMessage = function(data, validCommands) { + var message, _ref; + try { + message = JSON.parse(data); + } catch (e) { + throw new ProtocolError('unparsable JSON', data); + } + if (!message.command) { + throw new ProtocolError('missing "command" key', data); + } + if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { + throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); + } + return message; + }; + return Parser; +})(); + +// connector +// Generated by CoffeeScript 1.3.3 +var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref; + +_ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7; + +Version = '2.0.8'; + +__connector.Connector = Connector = (function() { + + function Connector(options, WebSocket, Timer, handlers) { + var _this = this; + this.options = options; + this.WebSocket = WebSocket; + this.Timer = Timer; + this.handlers = handlers; + this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload"; + this._nextDelay = this.options.mindelay; + this._connectionDesired = false; + this.protocol = 0; + this.protocolParser = new Parser({ + connected: function(protocol) { + _this.protocol = protocol; + _this._handshakeTimeout.stop(); + _this._nextDelay = _this.options.mindelay; + _this._disconnectionReason = 'broken'; + return _this.handlers.connected(protocol); + }, + error: function(e) { + _this.handlers.error(e); + return _this._closeOnError(); + }, + message: function(message) { + return _this.handlers.message(message); + } + }); + this._handshakeTimeout = new Timer(function() { + if (!_this._isSocketConnected()) { + return; + } + _this._disconnectionReason = 'handshake-timeout'; + return _this.socket.close(); + }); + this._reconnectTimer = new Timer(function() { + if (!_this._connectionDesired) { + return; + } + return _this.connect(); + }); + this.connect(); + } + + Connector.prototype._isSocketConnected = function() { + return this.socket && this.socket.readyState === this.WebSocket.OPEN; + }; + + Connector.prototype.connect = function() { + var _this = this; + this._connectionDesired = true; + if (this._isSocketConnected()) { + return; + } + this._reconnectTimer.stop(); + this._disconnectionReason = 'cannot-connect'; + this.protocolParser.reset(); + this.handlers.connecting(); + this.socket = new this.WebSocket(this._uri); + this.socket.onopen = function(e) { + return _this._onopen(e); + }; + this.socket.onclose = function(e) { + return _this._onclose(e); + }; + this.socket.onmessage = function(e) { + return _this._onmessage(e); + }; + return this.socket.onerror = function(e) { + return _this._onerror(e); + }; + }; + + Connector.prototype.disconnect = function() { + this._connectionDesired = false; + this._reconnectTimer.stop(); + if (!this._isSocketConnected()) { + return; + } + this._disconnectionReason = 'manual'; + return this.socket.close(); + }; + + Connector.prototype._scheduleReconnection = function() { + if (!this._connectionDesired) { + return; + } + if (!this._reconnectTimer.running) { + this._reconnectTimer.start(this._nextDelay); + return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2); + } + }; + + Connector.prototype.sendCommand = function(command) { + if (this.protocol == null) { + return; + } + return this._sendCommand(command); + }; + + Connector.prototype._sendCommand = function(command) { + return this.socket.send(JSON.stringify(command)); + }; + + Connector.prototype._closeOnError = function() { + this._handshakeTimeout.stop(); + this._disconnectionReason = 'error'; + return this.socket.close(); + }; + + Connector.prototype._onopen = function(e) { + var hello; + this.handlers.socketConnected(); + this._disconnectionReason = 'handshake-failed'; + hello = { + command: 'hello', + protocols: [PROTOCOL_6, PROTOCOL_7] + }; + hello.ver = Version; + if (this.options.ext) { + hello.ext = this.options.ext; + } + if (this.options.extver) { + hello.extver = this.options.extver; + } + if (this.options.snipver) { + hello.snipver = this.options.snipver; + } + this._sendCommand(hello); + return this._handshakeTimeout.start(this.options.handshake_timeout); + }; + + Connector.prototype._onclose = function(e) { + this.protocol = 0; + this.handlers.disconnected(this._disconnectionReason, this._nextDelay); + return this._scheduleReconnection(); + }; + + Connector.prototype._onerror = function(e) {}; + + Connector.prototype._onmessage = function(e) { + return this.protocolParser.process(e.data); + }; + + return Connector; + +})(); + +// timer +var Timer; +var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; +__timer.Timer = Timer = (function() { + function Timer(func) { + this.func = func; + this.running = false; + this.id = null; + this._handler = __bind(function() { + this.running = false; + this.id = null; + return this.func(); + }, this); + } + Timer.prototype.start = function(timeout) { + if (this.running) { + clearTimeout(this.id); + } + this.id = setTimeout(this._handler, timeout); + return this.running = true; + }; + Timer.prototype.stop = function() { + if (this.running) { + clearTimeout(this.id); + this.running = false; + return this.id = null; + } + }; + return Timer; +})(); +Timer.start = function(timeout, func) { + return setTimeout(func, timeout); +}; + +// options +var Options; +__options.Options = Options = (function() { + function Options() { + this.host = null; + this.port = 35729; + this.snipver = null; + this.ext = null; + this.extver = null; + this.mindelay = 1000; + this.maxdelay = 60000; + this.handshake_timeout = 5000; + } + Options.prototype.set = function(name, value) { + switch (typeof this[name]) { + case 'undefined': + break; + case 'number': + return this[name] = +value; + default: + return this[name] = value; + } + }; + return Options; +})(); +Options.extract = function(document) { + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2; + _ref = document.getElementsByTagName('script'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { + options = new Options(); + if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { + options.host = mm[1]; + if (mm[2]) { + options.port = parseInt(mm[2], 10); + } + } + if (m[2]) { + _ref2 = m[2].split('&'); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + pair = _ref2[_j]; + if ((keyAndValue = pair.split('=')).length > 1) { + options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); + } + } + } + return options; + } + } + return null; +}; + +// reloader +// Generated by CoffeeScript 1.3.1 +(function() { + var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + + splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash + }; + }; + + pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); + }; + + pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 + }; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; + } + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } + }; + + numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; + }; + + pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; + }; + + IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } + ]; + + __reloader.Reloader = Reloader = (function() { + + Reloader.name = 'Reloader'; + + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } + + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; + + Reloader.prototype.analyze = function(callback) { + return results; + }; + + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; + } + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { + return; + } + } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; + } + } + return this.reloadPage(); + }; + + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; + + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); + } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); + } + } + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); + } + return _results; + } + }; + + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (e) { + + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); + } + } + }; + + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len, + _this = this; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; + } + }); + if (newValue !== value) { + style[styleName] = newValue; + } + } + } + }; + + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, + _this = this; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) { + _results.push(link); + } + } + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); + } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); + } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), function(l) { + return pathFromUrl(_this.linkHref(l)); + }); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); + } else { + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); + } + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); + } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (e) { + + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; + } + } + } + }; + + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll, + _this = this; + callbackExecuted = false; + executeCallback = function() { + if (callbackExecuted) { + return; + } + callbackExecuted = true; + return func(); + }; + clone.onload = function() { + console.log("onload!"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); + }; + if (!this.knownToSupportCssOnLoad) { + (poll = function() { + if (clone.sheet) { + console.log("polling!"); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + })(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; + + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent, + _this = this; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; + } else { + additionalWaitingTime = 200; + } + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; + } + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; + }); + }); + }; + + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink, + _this = this; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); + } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + return parent.deleteRule(index + 1); + }); + }); + }; + + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; + + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); + } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; + } + } + return url + params + hash; + }; + + return Reloader; + + })(); + +}).call(this); + +// livereload +var Connector, LiveReload, Options, Reloader, Timer; + +Connector = __connector.Connector; + +Timer = __timer.Timer; + +Options = __options.Options; + +Reloader = __reloader.Reloader; + +__livereload.LiveReload = LiveReload = (function() { + + function LiveReload(window) { + var _this = this; + this.window = window; + this.listeners = {}; + this.plugins = []; + this.pluginIdentifiers = {}; + this.console = this.window.location.href.match(/LR-verbose/) && this.window.console && this.window.console.log && this.window.console.error ? this.window.console : { + log: function() {}, + error: function() {} + }; + if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) { + console.error("LiveReload disabled because the browser does not seem to support web sockets"); + return; + } + if (!(this.options = Options.extract(this.window.document))) { + console.error("LiveReload disabled because it could not find its own + + + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html new file mode 100644 index 000000000..e322f2aa8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html @@ -0,0 +1,44 @@ + + + + + WebSocket test + + + +

    WebSocket test

    +
      + + + + + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js new file mode 100644 index 000000000..eab3a461d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js @@ -0,0 +1,110 @@ +var API = require('./websocket/api'), + Event = require('./websocket/api/event'); + +var isSecureConnection = function(request) { + if (request.headers['x-forwarded-proto']) { + return request.headers['x-forwarded-proto'] === 'https'; + } else { + return (request.connection && request.connection.authorized !== undefined) || + (request.socket && request.socket.secure); + } +}; + +var EventSource = function(request, response, options) { + options = options || {}; + + this._request = request; + this._response = response; + this._stream = response.socket; + this._ping = options.ping || this.DEFAULT_PING; + this._retry = options.retry || this.DEFAULT_RETRY; + + var scheme = isSecureConnection(request) ? 'https:' : 'http:'; + this.url = scheme + '//' + request.headers.host + request.url; + + this.lastEventId = request.headers['last-event-id'] || ''; + + var self = this; + this.readyState = API.CONNECTING; + this._sendBuffer = []; + process.nextTick(function() { self._open() }); + + var handshake = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/event-stream\r\n' + + 'Cache-Control: no-cache, no-store\r\n' + + 'Connection: close\r\n' + + '\r\n\r\n' + + 'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n'; + + this.readyState = API.OPEN; + + if (this._ping) + this._pingLoop = setInterval(function() { self.ping() }, this._ping * 1000); + + if (!this._stream || !this._stream.writable) return; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + try { this._stream.write(handshake, 'utf8') } catch (e) {} + + ['close', 'end', 'error'].forEach(function(event) { + self._stream.addListener(event, function() { self.close() }); + }); +}; + +EventSource.isEventSource = function(request) { + var accept = (request.headers.accept || '').split(/\s*,\s*/); + return accept.indexOf('text/event-stream') >= 0; +}; + +var instance = { + DEFAULT_PING: 10, + DEFAULT_RETRY: 5, + + send: function(message, options) { + if (this.readyState !== API.OPEN) return false; + + message = String(message).replace(/(\r\n|\r|\n)/g, '$1data: '); + options = options || {}; + + var frame = ''; + if (options.event) frame += 'event: ' + options.event + '\r\n'; + if (options.id) frame += 'id: ' + options.id + '\r\n'; + frame += 'data: ' + message + '\r\n\r\n'; + + try { + this._stream.write(frame, 'utf8'); + return true; + } catch (e) { + return false; + } + }, + + ping: function() { + try { + this._stream.write(':\r\n\r\n', 'utf8'); + return true; + } catch (e) { + return false; + } + }, + + close: function() { + if (this.readyState === API.CLOSING || this.readyState === API.CLOSED) + return; + + this.readyState = API.CLOSED; + clearInterval(this._pingLoop); + this._response.end(); + + var event = new Event('close'); + event.initEvent('close', false, false); + this.dispatchEvent(event); + } +}; + +for (var key in API) EventSource.prototype[key] = API[key]; +for (var key in instance) EventSource.prototype[key] = instance[key]; +module.exports = EventSource; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js new file mode 100644 index 000000000..bbf9d29e4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js @@ -0,0 +1,93 @@ +// API and protocol references: +// +// * http://dev.w3.org/html5/websockets/ +// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget +// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-event +// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 +// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 +// * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 + +var Draft75Parser = require('./websocket/draft75_parser'), + Draft76Parser = require('./websocket/draft76_parser'), + HybiParser = require('./websocket/hybi_parser'), + API = require('./websocket/api'), + Event = require('./websocket/api/event'); + +var getParser = function(request) { + var headers = request.headers; + return headers['sec-websocket-version'] + ? HybiParser + : (headers['sec-websocket-key1'] && headers['sec-websocket-key2']) + ? Draft76Parser + : Draft75Parser; +}; + +var isSecureConnection = function(request) { + if (request.headers['x-forwarded-proto']) { + return request.headers['x-forwarded-proto'] === 'https'; + } else { + return (request.connection && request.connection.authorized !== undefined) || + (request.socket && request.socket.secure); + } +}; + +var WebSocket = function(request, socket, head, supportedProtos, options) { + this.request = request; + this._stream = request.socket; + this._ping = options && options.ping; + this._pingId = 0; + + var scheme = isSecureConnection(request) ? 'wss:' : 'ws:'; + this.url = scheme + '//' + request.headers.host + request.url; + this.readyState = API.CONNECTING; + this.bufferedAmount = 0; + + var Parser = getParser(request); + this._parser = new Parser(this, {protocols: supportedProtos}); + + var self = this; + this._sendBuffer = []; + process.nextTick(function() { self._open() }); + + var handshake = this._parser.handshakeResponse(head); + if (this._parser.isOpen()) this.readyState = API.OPEN; + + if (this._ping) + this._pingLoop = setInterval(function() { + self._pingId += 1; + self.ping(self._pingId.toString()); + }, this._ping * 1000); + + this.protocol = this._parser.protocol || ''; + this.version = this._parser.getVersion(); + + if (!this._stream || !this._stream.writable) return; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + try { this._stream.write(handshake, 'binary') } catch (e) {} + + this._stream.addListener('data', function(data) { + var response = self._parser.parse(data); + if (!response) return; + try { self._stream.write(response, 'binary') } catch (e) {} + self._open(); + }); + ['close', 'end', 'error'].forEach(function(event) { + self._stream.addListener(event, function() { self.close(1006, '', false) }); + }); +}; + +WebSocket.prototype.ping = function(message, callback, context) { + if (!this._parser.ping) return false; + return this._parser.ping(message, callback, context); +}; + +for (var key in API) WebSocket.prototype[key] = API[key]; + +WebSocket.WebSocket = WebSocket; +WebSocket.Client = require('./websocket/client'); +WebSocket.EventSource = require('./eventsource'); +module.exports = WebSocket; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js new file mode 100644 index 000000000..6c37e271f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js @@ -0,0 +1,88 @@ +var EventTarget = require('./api/event_target'), + Event = require('./api/event'); + +var API = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3, + + _open: function() { + if (this._parser && !this._parser.isOpen()) return; + this.readyState = API.OPEN; + + var buffer = this._sendBuffer || [], + message; + + while (message = buffer.shift()) + this.send.apply(this, message); + + var event = new Event('open'); + event.initEvent('open', false, false); + this.dispatchEvent(event); + }, + + receive: function(data) { + if (this.readyState !== API.OPEN) return false; + var event = new Event('message'); + event.initEvent('message', false, false); + event.data = data; + this.dispatchEvent(event); + }, + + send: function(data, type, errorType) { + if (this.readyState === API.CONNECTING) { + if (this._sendBuffer) { + this._sendBuffer.push(arguments); + return true; + } else { + throw new Error('Cannot call send(), socket is not open yet'); + } + } + + if (this.readyState === API.CLOSED) + return false; + + if (!(data instanceof Buffer)) data = String(data); + + var frame = this._parser.frame(data, type, errorType); + try { + this._stream.write(frame, 'binary'); + return true; + } catch (e) { + return false; + } + }, + + close: function(code, reason, ack) { + if (this.readyState === API.CLOSED) return; + if (this.readyState === API.CLOSING && ack !== false) return; + + var finalize = function() { + this.readyState = API.CLOSED; + if (this._pingLoop) clearInterval(this._pingLoop); + if (this._stream) this._stream.end(); + var event = new Event('close', {code: code || 1000, reason: reason || ''}); + event.initEvent('close', false, false); + this.dispatchEvent(event); + }; + + if (this.readyState === API.CONNECTING) + return finalize.call(this); + + this.readyState = API.CLOSING; + + if (ack === false) { + if (this._parser.close) this._parser.close(code, reason); + finalize.call(this); + } else { + if (this._parser.close) this._parser.close(code, reason, finalize, this); + else finalize.call(this); + } + } +}; + +for (var key in EventTarget) API[key] = EventTarget[key]; + +module.exports = API; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js new file mode 100644 index 000000000..2f707d84b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js @@ -0,0 +1,21 @@ +var Event = function(eventType, options) { + this.type = eventType; + for (var key in options) + this[key] = options[key]; +}; + +Event.prototype.initEvent = function(eventType, canBubble, cancelable) { + this.type = eventType; + this.bubbles = canBubble; + this.cancelable = cancelable; +}; + +Event.prototype.stopPropagation = function() {}; +Event.prototype.preventDefault = function() {}; + +Event.CAPTURING_PHASE = 1; +Event.AT_TARGET = 2; +Event.BUBBLING_PHASE = 3; + +module.exports = Event; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js new file mode 100644 index 000000000..056a8f451 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js @@ -0,0 +1,47 @@ +var Event = require('./event'); + +var EventTarget = { + onopen: null, + onmessage: null, + onerror: null, + onclose: null, + + addEventListener: function(eventType, listener, useCapture) { + this._listeners = this._listeners || {}; + var list = this._listeners[eventType] = this._listeners[eventType] || []; + list.push(listener); + }, + + removeEventListener: function(eventType, listener, useCapture) { + if (!this._listeners || !this._listeners[eventType]) return; + + if (!listener) { + delete this._listeners[eventType]; + return; + } + var list = this._listeners[eventType], + i = list.length; + + while (i--) { + if (listener !== list[i]) continue; + list.splice(i,1); + } + }, + + dispatchEvent: function(event) { + event.target = event.currentTarget = this; + event.eventPhase = Event.AT_TARGET; + + if (this['on' + event.type]) + this['on' + event.type](event); + + if (!this._listeners || !this._listeners[event.type]) return; + + this._listeners[event.type].forEach(function(listener) { + listener(event); + }, this); + } +}; + +module.exports = EventTarget; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js new file mode 100644 index 000000000..cde0002ae --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js @@ -0,0 +1,86 @@ +var net = require('net'), + tls = require('tls'); + +var HybiParser = require('./hybi_parser'), + API = require('./api'), + Event = require('./api/event'); + +var Client = function(url, protocols, options) { + this.url = url; + this._uri = require('url').parse(url); + + this.protocol = ''; + this.readyState = API.CONNECTING; + this.bufferedAmount = 0; + + var secure = (this._uri.protocol === 'wss:'), + self = this, + onConnect = function() { self._onConnect() }, + tlsOptions = {}; + + if (options && options.verify === false) tlsOptions.rejectUnauthorized = false; + + var connection = secure + ? tls.connect(this._uri.port || 443, this._uri.hostname, tlsOptions, onConnect) + : net.createConnection(this._uri.port || 80, this._uri.hostname); + + this._parser = new HybiParser(this, {masking: true, protocols: protocols}); + this._stream = connection; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + if (!secure) connection.addListener('connect', onConnect); + + connection.addListener('data', function(data) { + self._onData(data); + }); + ['close', 'end', 'error'].forEach(function(event) { + connection.addListener(event, function() { self.close(1006, '', false) }); + }); +}; + +Client.prototype._onConnect = function() { + this._handshake = this._parser.createHandshake(this._uri, this._stream); + this._message = []; + try { + this._stream.write(this._handshake.requestData(), 'binary'); + } catch (e) {} +}; + +Client.prototype._onData = function(data) { + switch (this.readyState) { + case API.CONNECTING: + var bytes = this._handshake.parse(data); + for (var i = 0, n = bytes.length; i < n; i++) + this._message.push(bytes[i]); + + if (!this._handshake.isComplete()) return; + + if (this._handshake.isValid()) { + this.protocol = this._handshake.protocol || ''; + this.readyState = API.OPEN; + var event = new Event('open'); + event.initEvent('open', false, false); + this.dispatchEvent(event); + + this._parser.parse(this._message); + + } else { + this.readyState = API.CLOSED; + var event = new Event('close', {code: 1006, reason: ''}); + event.initEvent('close', false, false); + this.dispatchEvent(event); + } + break; + + case API.OPEN: + case API.CLOSING: + this._parser.parse(data); + } +}; + +for (var key in API) Client.prototype[key] = API[key]; + +module.exports = Client; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js new file mode 100644 index 000000000..b4e00aa2e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js @@ -0,0 +1,98 @@ +var Draft75Parser = function(webSocket) { + this._socket = webSocket; + this._stage = 0; +}; + +var instance = { + getVersion: function() { + return 'hixie-75'; + }, + + handshakeResponse: function() { + return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + 'WebSocket-Origin: ' + this._socket.request.headers.origin + '\r\n' + + 'WebSocket-Location: ' + this._socket.url + '\r\n\r\n', + 'utf8'); + }, + + isOpen: function() { + return true; + }, + + parse: function(buffer) { + var data, message, value; + for (var i = 0, n = buffer.length; i < n; i++) { + data = buffer[i]; + + switch (this._stage) { + case 0: + this._parseLeadingByte(data); + break; + + case 1: + value = (data & 0x7F); + this._length = value + 128 * this._length; + + if (this._closing && this._length === 0) { + this._socket.close(null, null, false); + } + else if ((0x80 & data) !== 0x80) { + if (this._length === 0) { + this._socket.receive(''); + this._stage = 0; + } + else { + this._buffer = []; + this._stage = 2; + } + } + break; + + case 2: + if (data === 0xFF) { + message = new Buffer(this._buffer); + this._socket.receive(message.toString('utf8', 0, this._buffer.length)); + this._stage = 0; + } + else { + this._buffer.push(data); + if (this._length && this._buffer.length === this._length) + this._stage = 0; + } + break; + } + } + }, + + _parseLeadingByte: function(data) { + if ((0x80 & data) === 0x80) { + this._length = 0; + this._stage = 1; + } else { + delete this._length; + this._buffer = []; + this._stage = 2; + } + }, + + frame: function(data) { + if (Buffer.isBuffer(data)) return data; + + var buffer = new Buffer(data, 'utf8'), + frame = new Buffer(buffer.length + 2); + + frame[0] = 0x00; + frame[buffer.length + 1] = 0xFF; + buffer.copy(frame, 1); + + return frame; + } +}; + +for (var key in instance) + Draft75Parser.prototype[key] = instance[key]; + +module.exports = Draft75Parser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js new file mode 100644 index 000000000..82da1a049 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js @@ -0,0 +1,99 @@ +var crypto = require('crypto'), + Draft75Parser = require('./draft75_parser'), + Draft76Parser = function() { Draft75Parser.apply(this, arguments) }; + +var bridge = function() {}; +bridge.prototype = Draft75Parser.prototype; +Draft76Parser.prototype = new bridge(); + +var numberFromKey = function(key) { + return parseInt(key.match(/[0-9]/g).join(''), 10); +}; + +var spacesInKey = function(key) { + return key.match(/ /g).length; +}; + +var bigEndian = function(number) { + var string = ''; + [24,16,8,0].forEach(function(offset) { + string += String.fromCharCode(number >> offset & 0xFF); + }); + return string; +}; + +Draft76Parser.prototype.getVersion = function() { + return 'hixie-76'; +}; + +Draft76Parser.prototype.handshakeResponse = function(head) { + var request = this._socket.request, tmp; + + var response = new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + 'Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n' + + 'Sec-WebSocket-Location: ' + this._socket.url + '\r\n\r\n', + 'binary'); + + var signature = this.handshakeSignature(head); + if (signature) { + tmp = new Buffer(response.length + signature.length); + response.copy(tmp, 0); + signature.copy(tmp, response.length); + response = tmp; + } + + return response; +}; + +Draft76Parser.prototype.isOpen = function() { + return !!this._handshakeComplete; +}; + +Draft76Parser.prototype.handshakeSignature = function(head) { + if (head.length === 0) return null; + + var request = this._socket.request, + + key1 = request.headers['sec-websocket-key1'], + value1 = numberFromKey(key1) / spacesInKey(key1), + + key2 = request.headers['sec-websocket-key2'], + value2 = numberFromKey(key2) / spacesInKey(key2), + + MD5 = crypto.createHash('md5'); + + MD5.update(bigEndian(value1)); + MD5.update(bigEndian(value2)); + MD5.update(head.toString('binary')); + + this._handshakeComplete = true; + return new Buffer(MD5.digest('binary'), 'binary'); +}; + +Draft76Parser.prototype.parse = function(data) { + if (this._handshakeComplete) + return Draft75Parser.prototype.parse.call(this, data); + + return this.handshakeSignature(data); +}; + +Draft76Parser.prototype._parseLeadingByte = function(data) { + if (data !== 0xFF) + return Draft75Parser.prototype._parseLeadingByte.call(this, data); + + this._closing = true; + this._length = 0; + this._stage = 1; +}; + +Draft76Parser.prototype.close = function(code, reason, callback, context) { + if (this._closed) return; + if (this._closing) this._socket.send(new Buffer([0xFF, 0x00])); + this._closed = true; + if (callback) callback.call(context); +}; + +module.exports = Draft76Parser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js new file mode 100644 index 000000000..57464daaf --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js @@ -0,0 +1,355 @@ +var crypto = require('crypto'), + Handshake = require('./hybi_parser/handshake'), + Reader = require('./hybi_parser/stream_reader'); + +var HybiParser = function(webSocket, options) { + this._reset(); + this._socket = webSocket; + this._reader = new Reader(); + this._stage = 0; + this._masking = options && options.masking; + this._protocols = options && options.protocols; + + this._pingCallbacks = {}; + + if (typeof this._protocols === 'string') + this._protocols = this._protocols.split(/\s*,\s*/); +}; + +HybiParser.mask = function(payload, mask, offset) { + if (mask.length === 0) return payload; + offset = offset || 0; + + for (var i = 0, n = payload.length - offset; i < n; i++) { + payload[offset + i] = payload[offset + i] ^ mask[i % 4]; + } + return payload; +}; + +var instance = { + BYTE: 255, + FIN: 128, + MASK: 128, + RSV1: 64, + RSV2: 32, + RSV3: 16, + OPCODE: 15, + LENGTH: 127, + + OPCODES: { + continuation: 0, + text: 1, + binary: 2, + close: 8, + ping: 9, + pong: 10 + }, + + ERRORS: { + normal_closure: 1000, + going_away: 1001, + protocol_error: 1002, + unacceptable: 1003, + encoding_error: 1007, + policy_violation: 1008, + too_large: 1009, + extension_error: 1010, + unexpected_condition: 1011 + }, + + FRAGMENTED_OPCODES: [0,1,2], + OPENING_OPCODES: [1,2], + + ERROR_CODES: [1000,1001,1002,1003,1007,1008,1009,1010,1011], + + UTF8_MATCH: /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/, + + getVersion: function() { + var version = this._socket.request.headers['sec-websocket-version']; + return 'hybi-' + version; + }, + + handshakeResponse: function() { + var secKey = this._socket.request.headers['sec-websocket-key']; + if (!secKey) return null; + + var SHA1 = crypto.createHash('sha1'); + SHA1.update(secKey + Handshake.GUID); + + var accept = SHA1.digest('base64'), + protos = this._socket.request.headers['sec-websocket-protocol'], + supported = this._protocols, + proto, + + headers = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: Upgrade', + 'Sec-WebSocket-Accept: ' + accept + ]; + + if (protos !== undefined && supported !== undefined) { + if (typeof protos === 'string') protos = protos.split(/\s*,\s*/); + proto = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0]; + if (proto) { + this.protocol = proto; + headers.push('Sec-WebSocket-Protocol: ' + proto); + } + } + + return new Buffer(headers.concat('','').join('\r\n'), 'utf8'); + }, + + isOpen: function() { + return true; + }, + + createHandshake: function(uri) { + return new Handshake(uri, this._protocols); + }, + + parse: function(data) { + this._reader.put(data); + var buffer = true; + while (buffer) { + switch (this._stage) { + case 0: + buffer = this._reader.read(1); + if (buffer) this._parseOpcode(buffer[0]); + break; + + case 1: + buffer = this._reader.read(1); + if (buffer) this._parseLength(buffer[0]); + break; + + case 2: + buffer = this._reader.read(this._lengthSize); + if (buffer) this._parseExtendedLength(buffer); + break; + + case 3: + buffer = this._reader.read(4); + if (buffer) { + this._mask = buffer; + this._stage = 4; + } + break; + + case 4: + buffer = this._reader.read(this._length); + if (buffer) { + this._payload = buffer; + this._emitFrame(); + this._stage = 0; + } + break; + } + } + }, + + _parseOpcode: function(data) { + var rsvs = [this.RSV1, this.RSV2, this.RSV3].filter(function(rsv) { + return (data & rsv) === rsv; + }, this); + + if (rsvs.length > 0) return this._socket.close(this.ERRORS.protocol_error, null, false); + + this._final = (data & this.FIN) === this.FIN; + this._opcode = (data & this.OPCODE); + this._mask = []; + this._payload = []; + + var valid = false; + + for (var key in this.OPCODES) { + if (this.OPCODES[key] === this._opcode) + valid = true; + } + if (!valid) return this._socket.close(this.ERRORS.protocol_error, null, false); + + if (this.FRAGMENTED_OPCODES.indexOf(this._opcode) < 0 && !this._final) + return this._socket.close(this.ERRORS.protocol_error, null, false); + + if (this._mode && this.OPENING_OPCODES.indexOf(this._opcode) >= 0) + return this._socket.close(this.ERRORS.protocol_error, null, false); + + this._stage = 1; + }, + + _parseLength: function(data) { + this._masked = (data & this.MASK) === this.MASK; + this._length = (data & this.LENGTH); + + if (this._length >= 0 && this._length <= 125) { + this._stage = this._masked ? 3 : 4; + } else { + this._lengthBuffer = []; + this._lengthSize = (this._length === 126 ? 2 : 8); + this._stage = 2; + } + }, + + _parseExtendedLength: function(buffer) { + this._length = this._getInteger(buffer); + this._stage = this._masked ? 3 : 4; + }, + + frame: function(data, type, code) { + if (this._closed) return null; + + var isText = (typeof data === 'string'), + opcode = this.OPCODES[type || (isText ? 'text' : 'binary')], + buffer = isText ? new Buffer(data, 'utf8') : data, + insert = code ? 2 : 0, + length = buffer.length + insert, + header = (length <= 125) ? 2 : (length <= 65535 ? 4 : 10), + offset = header + (this._masking ? 4 : 0), + masked = this._masking ? this.MASK : 0, + frame = new Buffer(length + offset), + BYTE = this.BYTE, + mask, i; + + frame[0] = this.FIN | opcode; + + if (length <= 125) { + frame[1] = masked | length; + } else if (length <= 65535) { + frame[1] = masked | 126; + frame[2] = Math.floor(length / 256); + frame[3] = length & BYTE; + } else { + frame[1] = masked | 127; + frame[2] = Math.floor(length / Math.pow(2,56)) & BYTE; + frame[3] = Math.floor(length / Math.pow(2,48)) & BYTE; + frame[4] = Math.floor(length / Math.pow(2,40)) & BYTE; + frame[5] = Math.floor(length / Math.pow(2,32)) & BYTE; + frame[6] = Math.floor(length / Math.pow(2,24)) & BYTE; + frame[7] = Math.floor(length / Math.pow(2,16)) & BYTE; + frame[8] = Math.floor(length / Math.pow(2,8)) & BYTE; + frame[9] = length & BYTE; + } + + if (code) { + frame[offset] = Math.floor(code / 256) & BYTE; + frame[offset+1] = code & BYTE; + } + buffer.copy(frame, offset + insert); + + if (this._masking) { + mask = [Math.floor(Math.random() * 256), Math.floor(Math.random() * 256), + Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)]; + new Buffer(mask).copy(frame, header); + HybiParser.mask(frame, mask, offset); + } + + return frame; + }, + + ping: function(message, callback, context) { + message = message || ''; + if (callback) this._pingCallbacks[message] = [callback, context]; + return this._socket.send(message, 'ping'); + }, + + close: function(code, reason, callback, context) { + if (this._closed) return; + if (callback) this._closingCallback = [callback, context]; + this._socket.send(reason || '', 'close', code || this.ERRORS.normal_closure); + this._closed = true; + }, + + buffer: function(fragment) { + for (var i = 0, n = fragment.length; i < n; i++) + this._buffer.push(fragment[i]); + }, + + _emitFrame: function() { + var payload = HybiParser.mask(this._payload, this._mask), + opcode = this._opcode; + + if (opcode === this.OPCODES.continuation) { + if (!this._mode) return this._socket.close(this.ERRORS.protocol_error, null, false); + this.buffer(payload); + if (this._final) { + var message = new Buffer(this._buffer); + if (this._mode === 'text') message = this._encode(message); + this._reset(); + if (message !== null) this._socket.receive(message); + else this._socket.close(this.ERRORS.encoding_error, null, false); + } + } + else if (opcode === this.OPCODES.text) { + if (this._final) { + var message = this._encode(payload); + if (message !== null) this._socket.receive(message); + else this._socket.close(this.ERRORS.encoding_error, null, false); + } else { + this._mode = 'text'; + this.buffer(payload); + } + } + else if (opcode === this.OPCODES.binary) { + if (this._final) { + this._socket.receive(payload); + } else { + this._mode = 'binary'; + this.buffer(payload); + } + } + else if (opcode === this.OPCODES.close) { + var code = (payload.length >= 2) ? 256 * payload[0] + payload[1] : null, + reason = (payload.length > 2) ? this._encode(payload.slice(2)) : null; + + if (!(payload.length === 0) && + !(code !== null && code >= 3000 && code < 5000) && + this.ERROR_CODES.indexOf(code) < 0) + code = this.ERRORS.protocol_error; + + if (payload.length > 125 || (payload.length > 2 && !reason)) + code = this.ERRORS.protocol_error; + + this._socket.close(code, (payload.length > 2) ? reason : null, false); + if (this._closingCallback) + this._closingCallback[0].call(this._closingCallback[1]); + } + else if (opcode === this.OPCODES.ping) { + if (payload.length > 125) return this._socket.close(this.ERRORS.protocol_error, null, false); + this._socket.send(payload, 'pong'); + } + else if (opcode === this.OPCODES.pong) { + var callbacks = this._pingCallbacks, + message = this._encode(payload), + callback = callbacks[message]; + + delete callbacks[message]; + if (callback) callback[0].call(callback[1]); + } + }, + + _reset: function() { + this._mode = null; + this._buffer = []; + }, + + _encode: function(buffer) { + try { + var string = buffer.toString('binary', 0, buffer.length); + if (!this.UTF8_MATCH.test(string)) return null; + } catch (e) {} + return buffer.toString('utf8', 0, buffer.length); + }, + + _getInteger: function(bytes) { + var number = 0; + for (var i = 0, n = bytes.length; i < n; i++) + number += bytes[i] << (8 * (n - 1 - i)); + return number; + } +}; + +for (var key in instance) + HybiParser.prototype[key] = instance[key]; + +module.exports = HybiParser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js new file mode 100644 index 000000000..0a751911d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js @@ -0,0 +1,91 @@ +var crypto = require('crypto'); + +var Handshake = function(uri, protocols) { + this._uri = uri; + this._protocols = protocols; + + var buffer = new Buffer(16), i = 16; + while (i--) buffer[i] = Math.floor(Math.random() * 256); + this._key = buffer.toString('base64'); + + var SHA1 = crypto.createHash('sha1'); + SHA1.update(this._key + Handshake.GUID); + this._accept = SHA1.digest('base64'); + + var HTTPParser = process.binding('http_parser').HTTPParser, + parser = new HTTPParser(HTTPParser.RESPONSE || 'response'), + current = null, + self = this; + + this._nodeVersion = HTTPParser.RESPONSE ? 6 : 4; + this._complete = false; + this._headers = {}; + this._parser = parser; + + parser.onHeaderField = function(b, start, length) { + current = b.toString('utf8', start, start + length); + }; + parser.onHeaderValue = function(b, start, length) { + self._headers[current] = b.toString('utf8', start, start + length); + }; + parser.onHeadersComplete = function(info) { + self._status = info.statusCode; + var headers = info.headers; + if (!headers) return; + for (var i = 0, n = headers.length; i < n; i += 2) + self._headers[headers[i]] = headers[i+1]; + }; + parser.onMessageComplete = function() { + self._complete = true; + }; +}; + +Handshake.GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; + +Handshake.prototype.requestData = function() { + var u = this._uri; + + var headers = [ + 'GET ' + (u.pathname || '/') + (u.search || '') + ' HTTP/1.1', + 'Host: ' + u.hostname + (u.port ? ':' + u.port : ''), + 'Upgrade: websocket', + 'Connection: Upgrade', + 'Sec-WebSocket-Key: ' + this._key, + 'Sec-WebSocket-Version: 13' + ]; + + if (this._protocols) + headers.push('Sec-WebSocket-Protocol: ' + this._protocols.join(', ')); + + return new Buffer(headers.concat('','').join('\r\n'), 'utf8'); +}; + +Handshake.prototype.parse = function(data) { + var consumed = this._parser.execute(data, 0, data.length), + offset = (this._nodeVersion < 6) ? 1 : 0; + + return (consumed === data.length) ? [] : data.slice(consumed + offset); +}; + +Handshake.prototype.isComplete = function() { + return this._complete; +}; + +Handshake.prototype.isValid = function() { + if (this._status !== 101) return false; + + var upgrade = this._headers.Upgrade, + connection = this._headers.Connection, + protocol = this._headers['Sec-WebSocket-Protocol']; + + this.protocol = this._protocols && this._protocols.indexOf(protocol) >= 0 + ? protocol + : null; + + return upgrade && /^websocket$/i.test(upgrade) && + connection && connection.split(/\s*,\s*/).indexOf('Upgrade') >= 0 && + ((!this._protocols && !protocol) || this.protocol) && + this._headers['Sec-WebSocket-Accept'] === this._accept; +}; + +module.exports = Handshake; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js new file mode 100644 index 000000000..01e607f83 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js @@ -0,0 +1,43 @@ +var StreamReader = function() { + this._queue = []; + this._cursor = 0; +}; + +StreamReader.prototype.read = function(bytes) { + return this._readBuffer(bytes); +}; + +StreamReader.prototype.put = function(buffer) { + if (!buffer || buffer.length === 0) return; + if (!buffer.copy) buffer = new Buffer(buffer); + this._queue.push(buffer); +}; + +StreamReader.prototype._readBuffer = function(length) { + var buffer = new Buffer(length), + queue = this._queue, + remain = length, + n = queue.length, + i = 0, + chunk, offset, size; + + if (remain === 0) return buffer; + + while (remain > 0 && i < n) { + chunk = queue[i]; + offset = (i === 0) ? this._cursor : 0; + size = Math.min(remain, chunk.length - offset); + chunk.copy(buffer, length - remain, offset, offset + size); + remain -= size; + i += 1; + } + + if (remain > 0) return null; + + queue.splice(0, i-1); + this._cursor = (i === 1 ? this._cursor : 0) + size; + + return buffer; +}; + +module.exports = StreamReader; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json new file mode 100644 index 000000000..45888c972 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json @@ -0,0 +1,53 @@ +{ + "name": "faye-websocket", + "description": "Standards-compliant WebSocket server and client", + "homepage": "http://github.com/faye/faye-websocket-node", + "author": { + "name": "James Coglan", + "email": "jcoglan@gmail.com", + "url": "http://jcoglan.com/" + }, + "keywords": [ + "websocket", + "eventsource" + ], + "version": "0.4.4", + "engines": { + "node": ">=0.4.0" + }, + "main": "./lib/faye/websocket", + "devDependencies": { + "jsclass": "", + "pace": "" + }, + "scripts": { + "test": "node spec/runner.js" + }, + "bugs": { + "url": "http://github.com/faye/faye-websocket-node/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://www.opensource.org/licenses/mit-license.php" + } + ], + "repositories": [ + { + "type": "git", + "url": "git://github.com/faye/faye-websocket-node.git" + } + ], + "readme": "# faye-websocket\n\n* Travis CI build: [](http://travis-ci.org/faye/faye-websocket-node)\n* Autobahn tests: [server](http://faye.jcoglan.com/autobahn/servers/), [client](http://faye.jcoglan.com/autobahn/clients/)\n\nThis is a robust, general-purpose WebSocket implementation extracted from the\n[Faye](http://faye.jcoglan.com) project. It provides classes for easily building\nWebSocket servers and clients in Node. It does not provide a server itself, but\nrather makes it easy to handle WebSocket connections within an existing\n[Node](http://nodejs.org/) application. It does not provide any abstraction\nother than the standard [WebSocket API](http://dev.w3.org/html5/websockets/).\n\nIt also provides an abstraction for handling [EventSource](http://dev.w3.org/html5/eventsource/)\nconnections, which are one-way connections that allow the server to push data to\nthe client. They are based on streaming HTTP responses and can be easier to\naccess via proxies than WebSockets.\n\nThe server-side socket can process [draft-75](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75),\n[draft-76](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76),\n[hybi-07](http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07)\nand later versions of the protocol. It selects protocol versions automatically,\nsupports both `text` and `binary` messages, and transparently handles `ping`,\n`pong`, `close` and fragmented messages.\n\n\n## Handling WebSocket connections in Node\n\nYou can handle WebSockets on the server side by listening for HTTP Upgrade\nrequests, and creating a new socket for the request. This socket object exposes\nthe usual WebSocket methods for receiving and sending messages. For example this\nis how you'd implement an echo server:\n\n```js\nvar WebSocket = require('faye-websocket'),\n http = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('upgrade', function(request, socket, head) {\n var ws = new WebSocket(request, socket, head);\n \n ws.onmessage = function(event) {\n ws.send(event.data);\n };\n \n ws.onclose = function(event) {\n console.log('close', event.code, event.reason);\n ws = null;\n };\n});\n\nserver.listen(8000);\n```\n\nNote that under certain circumstances (notably a draft-76 client connecting\nthrough an HTTP proxy), the WebSocket handshake will not be complete after you\ncall `new WebSocket()` because the server will not have received the entire\nhandshake from the client yet. In this case, calls to `ws.send()` will buffer\nthe message in memory until the handshake is complete, at which point any\nbuffered messages will be sent to the client.\n\nIf you need to detect when the WebSocket handshake is complete, you can use the\n`onopen` event.\n\nIf the connection's protocol version supports it, you can call `ws.ping()` to\nsend a ping message and wait for the client's response. This method takes a\nmessage string, and an optional callback that fires when a matching pong message\nis received. It returns `true` iff a ping message was sent. If the client does\nnot support ping/pong, this method sends no data and returns `false`.\n\n```js\nws.ping('Mic check, one, two', function() {\n // fires when pong is received\n});\n```\n\n\n## Using the WebSocket client\n\nThe client supports both the plain-text `ws` protocol and the encrypted `wss`\nprotocol, and has exactly the same interface as a socket you would use in a web\nbrowser. On the wire it identifies itself as hybi-13.\n\n```js\nvar WebSocket = require('faye-websocket'),\n ws = new WebSocket.Client('ws://www.example.com/');\n\nws.onopen = function(event) {\n console.log('open');\n ws.send('Hello, world!');\n};\n\nws.onmessage = function(event) {\n console.log('message', event.data);\n};\n\nws.onclose = function(event) {\n console.log('close', event.code, event.reason);\n ws = null;\n};\n```\n\n\n## Subprotocol negotiation\n\nThe WebSocket protocol allows peers to select and identify the application\nprotocol to use over the connection. On the client side, you can set which\nprotocols the client accepts by passing a list of protocol names when you\nconstruct the socket:\n\n```js\nvar ws = new WebSocket.Client('ws://www.example.com/', ['irc', 'amqp']);\n```\n\nOn the server side, you can likewise pass in the list of protocols the server\nsupports after the other constructor arguments:\n\n```js\nvar ws = new WebSocket(request, socket, head, ['irc', 'amqp']);\n```\n\nIf the client and server agree on a protocol, both the client- and server-side\nsocket objects expose the selected protocol through the `ws.protocol` property.\nIf they cannot agree on a protocol to use, the client closes the connection.\n\n\n## WebSocket API\n\nThe WebSocket API consists of several event handlers and a method for sending\nmessages.\n\n* onopen fires when the socket connection is established. Event\n has no attributes.\n* onerror fires when the connection attempt fails. Event has no\n attributes.\n* onmessage fires when the socket receives a message. Event has\n one attribute, data, which is either a `String` (for text\n frames) or a `Buffer` (for binary frames).\n* onclose fires when either the client or the server closes the\n connection. Event has two optional attributes, code and\n reason, that expose the status code and message sent by the\n peer that closed the connection.\n* send(message) accepts either a `String` or a `Buffer` and\n sends a text or binary message over the connection to the other peer.\n* close(code, reason) closes the connection, sending the given\n status code and reason text, both of which are optional.\n* protocol is a string (which may be empty) identifying the\n subprotocol the socket is using.\n\n\n## Handling EventSource connections in Node\n\nEventSource connections provide a very similar interface, although because they\nonly allow the server to send data to the client, there is no `onmessage` API.\nEventSource allows the server to push text messages to the client, where each\nmessage has an optional event-type and ID.\n\n```js\nvar WebSocket = require('faye-websocket'),\n EventSource = WebSocket.EventSource,\n http = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('request', function(request, response) {\n if (EventSource.isEventSource(request)) {\n var es = new EventSource(request, response);\n console.log('open', es.url, es.lastEventId);\n \n // Periodically send messages\n var loop = setInterval(function() { es.send('Hello') }, 1000);\n \n es.onclose = function() {\n clearInterval(loop);\n es = null;\n };\n \n } else {\n // Normal HTTP request\n response.writeHead(200, {'Content-Type': 'text/plain'});\n response.write('Hello');\n response.end();\n }\n});\n\nserver.listen(8000);\n```\n\nThe `send` method takes two optional parameters, `event` and `id`. The default\nevent-type is `'message'` with no ID. For example, to send a `notification`\nevent with ID `99`:\n\n```js\nes.send('Breaking News!', {event: 'notification', id: '99'});\n```\n\nThe `EventSource` object exposes the following properties:\n\n* url is a string containing the URL the client used to create\n the EventSource.\n* lastEventId is a string containing the last event ID\n received by the client. You can use this when the client reconnects after a\n dropped connection to determine which messages need resending.\n\nWhen you initialize an EventSource with ` new EventSource()`, you can pass\nconfiguration options after the `response` parameter. Available options are:\n\n* retry is a number that tells the client how long (in seconds)\n it should wait after a dropped connection before attempting to reconnect.\n* ping is a number that tells the server how often (in seconds)\n to send 'ping' packets to the client to keep the connection open, to defeat\n timeouts set by proxies. The client will ignore these messages.\n\nFor example, this creates a connection that pings every 15 seconds and is\nretryable every 10 seconds if the connection is broken:\n\n```js\nvar es = new EventSource(request, response, {ping: 15, retry: 10});\n```\n\nYou can send a ping message at any time by calling `es.ping()`. Unlike WebSocket,\nthe client does not send a response to this; it is merely to send some data over\nthe wire to keep the connection alive.\n\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2013 James Coglan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the 'Software'), to deal in\nthe Software without restriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the\nSoftware, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies 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, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n", + "readmeFilename": "README.markdown", + "repository": { + "type": "git", + "url": "git://github.com/faye/faye-websocket-node.git" + }, + "_id": "faye-websocket@0.4.4", + "dist": { + "shasum": "e2754bb036b23686059f1ae0cc5f9f34476c6306" + }, + "_from": "faye-websocket@~0.4.3", + "_resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js new file mode 100644 index 000000000..e9aa6bc6f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js @@ -0,0 +1,175 @@ +var Client = require('../../../lib/faye/websocket/client') + +JS.ENV.WebSocketSteps = JS.Test.asyncSteps({ + server: function(port, secure, callback) { + this._adapter = new EchoServer() + this._adapter.listen(port, secure) + this._port = port + setTimeout(callback, 100) + }, + + stop: function(callback) { + this._adapter.stop() + setTimeout(callback, 100) + }, + + open_socket: function(url, protocols, callback) { + var done = false, + self = this, + + resume = function(open) { + if (done) return + done = true + self._open = open + callback() + } + + this._ws = new Client(url, protocols, {verify: false}) + + this._ws.onopen = function() { resume(true) } + this._ws.onclose = function() { resume(false) } + }, + + close_socket: function(callback) { + var self = this + this._ws.onclose = function() { + self._open = false + callback() + } + this._ws.close() + }, + + check_open: function(callback) { + this.assert( this._open ) + callback() + }, + + check_closed: function(callback) { + this.assert( !this._open ) + callback() + }, + + check_protocol: function(protocol, callback) { + this.assertEqual( protocol, this._ws.protocol ) + callback() + }, + + listen_for_message: function(callback) { + var self = this + this._ws.addEventListener('message', function(message) { self._message = message.data }) + callback() + }, + + send_message: function(message, callback) { + this._ws.send(message) + setTimeout(callback, 100) + }, + + check_response: function(message, callback) { + this.assertEqual( message, this._message ) + callback() + }, + + check_no_response: function(callback) { + this.assert( !this._message ) + callback() + } +}) + + +JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) { + include(WebSocketSteps) + + before(function() { + this.protocols = ["foo", "echo"] + this.plain_text_url = "ws://localhost:8000/bayeux" + this.secure_url = "wss://localhost:8000/bayeux" + }) + + sharedBehavior("socket client", function() { with(this) { + it("can open a connection", function() { with(this) { + open_socket(socket_url, protocols) + check_open() + check_protocol("echo") + }}) + + it("cannot open a connection with unacceptable protocols", function() { with(this) { + open_socket(socket_url, ["foo"]) + check_closed() + }}) + + it("can close the connection", function() { with(this) { + open_socket(socket_url, protocols) + close_socket() + check_closed() + }}) + + describe("in the OPEN state", function() { with(this) { + before(function() { with(this) { + open_socket(socket_url, protocols) + }}) + + it("can send and receive messages", function() { with(this) { + listen_for_message() + send_message("I expect this to be echoed") + check_response("I expect this to be echoed") + }}) + + it("sends numbers as strings", function() { with(this) { + listen_for_message() + send_message(13) + check_response("13") + }}) + + it("sends booleans as strings", function() { with(this) { + listen_for_message() + send_message(false) + check_response("false") + }}) + + it("sends arrays as strings", function() { with(this) { + listen_for_message() + send_message([13,14,15]) + check_response("13,14,15") + }}) + }}) + + describe("in the CLOSED state", function() { with(this) { + before(function() { with(this) { + open_socket(socket_url, protocols) + close_socket() + }}) + + it("cannot send and receive messages", function() { with(this) { + listen_for_message() + send_message("I expect this to be echoed") + check_no_response() + }}) + }}) + }}) + + describe("with a plain-text server", function() { with(this) { + before(function() { + this.socket_url = this.plain_text_url + this.blocked_url = this.secure_url + }) + + before(function() { this.server(8000, false) }) + after (function() { this.stop() }) + + behavesLike("socket client") + }}) + + describe("with a secure server", function() { with(this) { + before(function() { + this.socket_url = this.secure_url + this.blocked_url = this.plain_text_url + }) + + before(function() { this.server(8000, true) }) + after (function() { this.stop() }) + + behavesLike("socket client") + }}) +}}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js new file mode 100644 index 000000000..619719350 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js @@ -0,0 +1,72 @@ +var Draft75Parser = require('../../../lib/faye/websocket/draft75_parser') + +JS.ENV.Draft75ParserSpec = JS.Test.describe("Draft75Parser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new Draft75Parser(webSocket) + }}) + + describe("parse", function() { with(this) { + sharedBehavior("draft-75 parser", function() { with(this) { + it("parses text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses multiple frames from the same packet", function() { with(this) { + expect(webSocket, "receive").given("Hello").exactly(2) + parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses text frames beginning 0x00-0x7F", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x66, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("ignores frames with a length header", function() { with(this) { + expect(webSocket, "receive").exactly(0) + parser.parse([0x80, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses text following an ignored block", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x80, 0x02, 0x48, 0x65, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]) + }}) + + it("parses frames received in several packets", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65]) + parser.parse([0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]) + }}) + + it("parses fragmented frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x00, 0x48, 0x65, 0x6c]) + parser.parse([0x6c, 0x6f, 0xff]) + }}) + }}) + + behavesLike("draft-75 parser") + + it("does not close the socket if a 76 close frame is received", function() { with(this) { + expect(webSocket, "close").exactly(0) + expect(webSocket, "receive").given("") + parser.parse([0xFF, 0x00]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js new file mode 100644 index 000000000..775c1e394 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js @@ -0,0 +1,28 @@ +var Draft76Parser = require('../../../lib/faye/websocket/draft76_parser') + +JS.ENV.Draft76ParserSpec = JS.Test.describe("Draft76Parser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new Draft76Parser(webSocket) + parser._handshakeComplete = true + }}) + + describe("parse", function() { with(this) { + behavesLike("draft-75 parser") + + it("closes the socket if a close frame is received", function() { with(this) { + expect(webSocket, "close") + parser.parse([0xFF, 0x00]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js new file mode 100644 index 000000000..5531b9d5f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js @@ -0,0 +1,148 @@ +var HybiParser = require('../../../lib/faye/websocket/hybi_parser') + +JS.ENV.HybiParserSpec = JS.Test.describe("HybiParser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new HybiParser(webSocket) + }}) + + define("parse", function() { + var bytes = []; + for (var i = 0, n = arguments.length; i < n; i++) bytes = bytes.concat(arguments[i]) + this.parser.parse(new Buffer(bytes)) + }) + + define("buffer", function(string) { + return { + equals: function(buffer) { + return buffer.toString('utf8', 0, buffer.length) === string + } + } + }) + + describe("parse", function() { with(this) { + define("mask", function() { + return this._mask = this._mask || [1,2,3,4].map(function() { return Math.floor(Math.random() * 255) }) + }) + + define("maskMessage", function(bytes) { + var output = [] + Array.prototype.forEach.call(bytes, function(b, i) { + output[i] = bytes[i] ^ this.mask()[i % 4] + }, this) + return output + }) + + it("parses unmasked text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses multiple frames from the same packet", function() { with(this) { + expect(webSocket, "receive").given("Hello").exactly(2) + parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses empty text frames", function() { with(this) { + expect(webSocket, "receive").given("") + parse([0x81, 0x00]) + }}) + + it("parses fragmented text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x01, 0x03, 0x48, 0x65, 0x6c]) + parse([0x80, 0x02, 0x6c, 0x6f]) + }}) + + it("parses masked text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x81, 0x85], mask(), maskMessage([0x48, 0x65, 0x6c, 0x6c, 0x6f])) + }}) + + it("parses masked empty text frames", function() { with(this) { + expect(webSocket, "receive").given("") + parse([0x81, 0x80], mask(), maskMessage([])) + }}) + + it("parses masked fragmented text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x01, 0x81], mask(), maskMessage([0x48])) + parse([0x80, 0x84], mask(), maskMessage([0x65, 0x6c, 0x6c, 0x6f])) + }}) + + it("closes the socket if the frame has an unrecognized opcode", function() { with(this) { + expect(webSocket, "close").given(1002, null, false) + parse([0x83, 0x00]) + }}) + + it("closes the socket if a close frame is received", function() { with(this) { + expect(webSocket, "close").given(1000, "Hello", false) + parse([0x88, 0x07, 0x03, 0xe8, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses unmasked multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]) + }}) + + it("parses frames received in several packets", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c]) + parse([0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]) + }}) + + it("parses fragmented multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x01, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3]) + parse([0x80, 0x01, 0xbf]) + }}) + + it("parses masked multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x8b], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf])) + }}) + + it("parses masked fragmented multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x01, 0x8a], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3])) + parse([0x80, 0x81], mask(), maskMessage([0xbf])) + }}) + + it("parses unmasked medium-length text frames", function() { with(this) { + expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") + parse([129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111]) + }}) + + it("parses masked medium-length text frames", function() { with(this) { + expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") + parse([129, 254, 0, 200], mask(), maskMessage([72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111])) + }}) + + it("replies to pings with a pong", function() { with(this) { + expect(webSocket, "send").given(buffer("OHAI"), "pong") + parse([0x89, 0x04, 0x4f, 0x48, 0x41, 0x49]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf], parser.frame("Apple = ") ) + }}) + + it("encodes medium-length strings using extra length bytes", function() { with(this) { + assertBufferEqual( [129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111], parser.frame("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") ) + }}) + + it("encodes close frames with an error code", function() { with(this) { + assertBufferEqual( [0x88, 0x07, 0x03, 0xea, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello", "close", 1002) ) + }}) + + it("encodes pong frames", function() { with(this) { + assertBufferEqual( [0x8a, 0x00], parser.frame("", "pong") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js new file mode 100644 index 000000000..68ad93e66 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js @@ -0,0 +1,54 @@ +require('jsclass') + +var WebSocket = require('../lib/faye/websocket'), + fs = require('fs'), + http = require('http'), + https = require('https') + + +JS.ENV.EchoServer = function() {} +EchoServer.prototype.listen = function(port, ssl) { + var server = ssl + ? https.createServer({ + key: fs.readFileSync(__dirname + '/server.key'), + cert: fs.readFileSync(__dirname + '/server.crt') + }) + : http.createServer() + + server.addListener('upgrade', function(request, socket, head) { + var ws = new WebSocket(request, socket, head, ["echo"]) + ws.onmessage = function(event) { + ws.send(event.data) + } + }) + this._httpServer = server + server.listen(port) +} +EchoServer.prototype.stop = function(callback, scope) { + this._httpServer.addListener('close', function() { + if (callback) callback.call(scope); + }); + this._httpServer.close(); +} + + +JS.Packages(function() { with(this) { + autoload(/.*Spec/, {from: 'spec/faye/websocket'}) +}}) + + +JS.require('JS.Test', function() { + JS.Test.Unit.Assertions.define("assertBufferEqual", function(array, buffer) { + this.assertEqual(array.length, buffer.length); + var ary = [], n = buffer.length; + while (n--) ary[n] = buffer[n]; + this.assertEqual(array, ary); + }) + + JS.require( 'ClientSpec', + 'Draft75ParserSpec', + 'Draft76ParserSpec', + 'HybiParserSpec', + JS.Test.method('autorun')) +}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt new file mode 100644 index 000000000..ade70de03 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICZTCCAc4CCQDxyrJZrFA0vjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJV +SzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBEZh +eWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJARYRamNvZ2xh +bkBnbWFpbC5jb20wHhcNMTEwODMwMTIzOTM2WhcNMTIwODI5MTIzOTM2WjB3MQsw +CQYDVQQGEwJVSzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTAL +BgNVBAoTBEZheWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJ +ARYRamNvZ2xhbkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AMDjU5fAK7fvUCZIYHcGXDZD/m9bY+B/UcwGcowk0hMQGYNlLKrpiK7xXBmZpDb6 +r8n+7L/epBeSumbRIm4TDzeNHhuQGYLIeGQy7JNLoPBr6GxubjuJhKOOBnCqcupR +CLGG7Zw5oL4UvtZVH6kL9XnjyokQQbxxeoV9DqtqOaHHAgMBAAEwDQYJKoZIhvcN +AQEFBQADgYEAvQjSpzE1ahaeH1CmbLwckTxvWMZfxcZOrxTruK1po3cNnDOjGqFQ +KEkNj3K5WfwTBD4QgUdYDykhDX2m6HaMz4JEbgrwQv8M8FiswIA3dyGsbOifOk8H +r3GPNKMzm4o6vrn6RGOpt9q6bsWUBUHfNpP93uU2C9QEwDua3cFjDA0= +-----END CERTIFICATE----- diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key new file mode 100644 index 000000000..85aba2d1e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDA41OXwCu371AmSGB3Blw2Q/5vW2Pgf1HMBnKMJNITEBmDZSyq +6Yiu8VwZmaQ2+q/J/uy/3qQXkrpm0SJuEw83jR4bkBmCyHhkMuyTS6Dwa+hsbm47 +iYSjjgZwqnLqUQixhu2cOaC+FL7WVR+pC/V548qJEEG8cXqFfQ6rajmhxwIDAQAB +AoGABlk1DiCQD8y7mZb2PdSiwlJ4lFewsNnf6lQn/v7TPzdfb5ir4LAxBHkDLACH +jBuyH3bZefMs+W2l3u5xMKhF7uJqYcUlJdH2UwRfNG54Hn4SGAjQOK3ONer99sUf +USlsWSX1HjAAFMCBwUfKxMZA3VNQfYKTPdm0jSVf85kHO1ECQQD3s6ksm3QpfD0L +eG9EoDrqmwnEfpKoWPpz1O0i5tY9VcmhmLwS5Zpd7lB1qjTqzZk4RygU73T/BseJ +azehIHK5AkEAx1mSXt+ec8RfzVi/io6oqi2vOcACXRbOG4NQmqUWPnumdwsJjsjR +RzEoDFC2lu6448p9sgEq+CkbmgVeiyp4fwJAQnmgySve/NMuvslPcyddKGD7OhSN +30ghzrwx98/jZwqC1i9bKeccimDOjwVitjD/Ea9m/ldVGqwDGMoBX+iJYQJAEIOO +CYfyw1pQKV2huGOq+zX/nwQV7go2lrbhFX55gkGR/6iNaSOfmosq6yJAje5GqLAc +i4NnQNl+7NpnA5ZIFwJBAI1+OsZyjbRI99pYkTdOpa5IPlIb3j3JbSfjAWHLxlRY +0HLvN3Q1mE9kbB+uKH6syF/S7nALgsLgq7eHYvIaE/A= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore new file mode 100644 index 000000000..2e84c1351 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore @@ -0,0 +1 @@ +.travis.yml diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js new file mode 100644 index 000000000..f8fe9eeb7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js @@ -0,0 +1,94 @@ + +var fs = require('fs'); + +// Collectable Mixin +// +// Provides utility methods to read from stdin and remaining arguments. +var collectable = module.exports; + +// XXX: tomdocify, generate in readme + +collectable.stdin = function stdin(force, done) { + if(!done) done = force, force = false; + var argv = this.nopt.argv; + var self = this; + done = done || function(err) { err && self.emit('error', err); }; + + this._readFromStdin = true; + + // not parsed, register done to be read when parse is called + if(!argv) { + this.once('stdin', done); + return this; + } + + // only read from stdin when no reamining args and not forced + if(!argv.remain.length || force) { + this.readStdin(done); + } + + return this; +}; + +// Read files from remaining args, concat the result and call back the `done` +// function with the concatanated result and the list of files. +collectable.files = function files(done) { + var argv = this.nopt.argv; + var self = this; + done = done || function(err) { err && self.emit('error', err); }; + + // not parsed, register done to be read when parse is called + if(!argv) { + this.once('files', done); + return this; + } + + // only read files when we actually have files to read from + if(argv.remain.length) { + this.readFiles(argv.remain, done); + } + + return this; +}; + +collectable.readStdin = function readStdin(done) { + var data = ''; + var self = this; + process.stdin.setEncoding('utf8'); + process.stdin.on('error', done); + process.stdin.on('data', function(chunk){ + data += chunk; + self.emit('stdin:data', chunk); + }).on('end', function(){ + self.emit('stdin', null, data); + done(null, data); + }).resume(); + return this; +}; + +// Asynchronous walk of the remaining args, reading the content and returns +// the concatanated result. +collectable.readFiles = function readFiles(filepaths, done) { + var data = ''; + var self = this; + var files = filepaths.slice(0); + (function read(file) { + if(!file) { + self.emit('files', null, data, filepaths); + return done(null, data, filepaths); + } + fs.readFile(file, 'utf8', function(err, body) { + if(err) return done(err); + data += body; + self.emit('files:data', body); + read(files.shift()); + }); + })(files.shift()); + return this; +}; + +// Collect data either from stdin or the list of remaining args +collectable.collect = function collect(done) { + return this.stdin(done).files(done); +}; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js new file mode 100644 index 000000000..60d3e5c4c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js @@ -0,0 +1,68 @@ +var nopt = require('nopt'); + +// Commandable Mixin +// +// Provides API to route arbitrary routes or register command / sub commands / +// sub programs. +var commandable = module.exports; + +// XXX: tomdocify, generate in readme + +commandable.cmd = +commandable.command = function command(name, fn) { + this._commands[name] = fn; + var commandable = fn && fn.command && fn.route && fn.parse; + this.on(name, commandable ? function(args, opts, position) { + fn.parse(args, position); + } : fn); + return this; +}; + +commandable.route = function route(pattern, fn) { + pattern = pattern instanceof RegExp ? pattern : new RegExp('^' + pattern + '$'); + this._routes.push({ + pattern: pattern, + fn: fn + }); + return this; +}; + +commandable.routeCommand = function routeCommand(opts) { + opts = opts || this.nopt; + var args = opts.argv.remain; + var commands = Object.keys(this._commands); + + // firt try to find a route, then fallback to command + var route = this._routes.filter(function(route) { + return route.pattern.test(args.join(' ')); + }); + + if(route.length) return route[0].fn(); + + var first = 0 + var registered = args.filter(function(arg, i) { + var match = ~commands.indexOf(arg); + if(match) first = first || i; + return match; + }); + + if(!registered[0]) return this.run(); + + opts.argv.remain = args.slice(0, first); + registered.forEach(function(command) { + var position = opts.argv.original.indexOf(command) + 1; + var options = nopt({}, {}, opts.argv.original, position); + this.emit(command, options.argv.original, options, position); + }, this); +}; + + +commandable.registered = function(args) { + var commands = Object.keys(this._commands); + var registered = args.filter(function(arg, i) { + return ~commands.indexOf(arg); + }); + + return registered.length ? this._commands[registered] : false; +}; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js new file mode 100644 index 000000000..0469cf8f9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js @@ -0,0 +1,253 @@ + +var fs = require('fs'); +var path = require('path'); +var nopt = require('nopt'); +var util = require('./util'); +var events = require('events'); + +var collectable = require('./actions/collectable'); +var commandable = require('./actions/commandable'); + +module.exports = noptify; +noptify.Noptify = Noptify; + +// noptify is a little wrapper around `nopt` module adding a more expressive, +// commander-like, API and few helpers. +// +// Examples +// +// var program = noptify(process.argv, { program: 'name' }) +// .version('0.0.1') +// .option('port', '-p', 'Port to listen on (default: 35729)', Number) +// .option('pid', 'Path to the generated PID file', String) +// +// var opts = program.parse(); +// +// Returns an instance of `Noptify` +function noptify(args, options) { + return new Noptify(args, options); +} + +// Noptify provides the API to parse out option, shorthands and generate the +// proper generic help output. +// +// - args - The Array of arguments to parse (default: `process.argv`); +// - options - An hash of options with the following properties +// - program - The program name to use in usage output +// +// Every noptify instance is created with two options, `-h, --help` and `-v, +// --version`. +function Noptify(args, options) { + events.EventEmitter.call(this); + options = this.options = options || {}; + this.args = args || process.argv; + this._program = options.program || (path.basename(this.args[this.args[0] === 'node' ? 1 : 0])); + + this._shorthands = {}; + this._commands = {}; + this._routes = []; + this._steps = []; + this.nopt = {}; + + this.option('help', '-h', 'Show help usage'); + this.option('version', '-v', 'Show package version'); +} + +util.inherits(Noptify, events.EventEmitter); + +// Inherits from each actions' mixins +// +// XXX: consider making it optional? with a `.use()` method? +util.extend(Noptify.prototype, collectable); +util.extend(Noptify.prototype, commandable); + + +// Parse the provided options and shorthands, pass them through `nopt` and +// return the result. +// +// When `opts.help` is set, the help output is displayed and `help` +// event is emitted. The process exists with `0` status, the help output is +// automatically displayed and the `help` event is emitted. +// +// Examples +// +// var program = noptify(['foo', '--help']) +// .on('help', function() { +// console.log('Examples'); +// console.log(''); +// console.log(' foo bar --baz > foo.txt'); +// }); +// +// var opts = program.parse(); +// // ... Help output ... +// // ... Custom help output ... +// // ... Exit ... +// +// +Noptify.prototype.parse = function parse(argv, position) { + argv = argv || this.args; + var options = this._options.reduce(function(opts, opt) { + opts[opt.name] = opt.type; + return opts; + }, {}); + + this._options.forEach(function(opt) { + if(!opt.shorthand) return; + this.shorthand(opt.shorthand, '--' + opt.name); + }, this); + + var opts = nopt(options, this._shorthands, argv, position); + if(opts.version) { + console.log(this._version); + process.exit(0); + } + + var registered = this.registered(opts.argv.remain); + if(opts.help) { + if(registered && registered.help) { + registered.help().emit('help'); + } else { + this.help().emit('help'); + } + + process.exit(0); + } + + this.nopt = opts; + + // check remaining args and registered command, for each match, remove the + // argument from remaining args and trigger the handler, ideally the handler + // can be another subprogram, for now simple functions + + if(this.routeCommand) process.nextTick(this.routeCommand.bind(this)); + if(this.stdin && this._readFromStdin) process.nextTick(this.stdin.bind(this)); + return opts; +}; + +// Define the program version. +Noptify.prototype.version = function version(ver) { + this._version = ver; + return this; +}; + +// Define the program property. +Noptify.prototype.program = function program(value) { + this._program = value || ''; + return this; +}; + +// Define `name` option with optional shorthands, optional description and optional type. +Noptify.prototype.option = function option(name, shorthand, description, type) { + this._options = this._options || []; + if(!description) { + description = shorthand; + shorthand = ''; + } + + if(!type) { + if(typeof description === 'function') { + type = description; + description = shorthand; + shorthand = ''; + } else { + type = String; + } + } + + shorthand = shorthand.replace(/^-*/, ''), + + this._options.push({ + name: name, + shorthand: shorthand.replace(/^-*/, ''), + description: description || (name + ': ' + type.name), + usage: (shorthand ? '-' + shorthand + ', ': '' ) + '--' + name, + type: type + }); + + return this; +}; + +// Stores the given `shorthands` Hash of options to be `parse()`-d by nopt +// later on. + +Noptify.prototype.shorthand = +Noptify.prototype.shorthands = function shorthands(options, value) { + if(typeof options === 'string' && value) { + this._shorthands[options] = value; + return this; + } + + Object.keys(options).forEach(function(shorthand) { + this._shorthands[shorthand] = options[shorthand]; + }, this); + return this; +}; + +// Simply output to stdout the Usage and Help output. +Noptify.prototype.help = function help() { + var buf = ''; + buf += '\n Usage: ' + this._program + ' [options]'; + buf += '\n'; + buf += '\n Options:\n'; + + var maxln = Math.max.apply(Math, this._options.map(function(opts) { + return opts.usage.length; + })); + + var options = this._options.map(function(opts) { + return ' ' + pad(opts.usage, maxln + 5) + '\t- ' + opts.description; + }); + + buf += options.join('\n'); + + // part of help input ? --list-shorthands ? + var shorthands = Object.keys(this._shorthands); + if(shorthands.length) { + buf += '\n\n Shorthands:\n'; + maxln = Math.max.apply(Math, Object.keys(this._shorthands).map(function(key) { + return key.length; + })); + buf += Object.keys(this._shorthands).map(function(shorthand) { + return ' --' + pad(shorthand, maxln + 1) + '\t\t' + this._shorthands[shorthand]; + }, this).join('\n'); + } + + buf += '\n'; + + console.log(buf); + return this; +}; + +// Helpers + +// command API + +Noptify.prototype.run = function run(fn) { + if(fn) { + this._steps.push(fn); + return this; + } + + if(!this.nopt.argv) return this.parse(); + + var steps = this._steps; + var self = this; + (function next(step) { + if(!step) return; + var async = /function\s*\(\w+/.test(step + ''); + if(!async) { + step(); + return next(steps.shift()); + } + + step(function(err) { + if(err) return self.emit('error', err); + next(steps.shift()); + }); + })(steps.shift()); +}; + +function pad(str, max) { + var ln = max - str.length; + return ln > 0 ? str + new Array(ln).join(' ') : str; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt new file mode 120000 index 000000000..6b6566ea7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/.npmignore new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md new file mode 100644 index 000000000..f290da8f4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js new file mode 100755 index 000000000..df90c729a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js new file mode 100755 index 000000000..142447e18 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js new file mode 100644 index 000000000..5763860ad --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js @@ -0,0 +1,555 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 000000000..99746fe67 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js new file mode 100644 index 000000000..bee4132c9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,111 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") +var util = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json new file mode 100644 index 000000000..55ed011bf --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,28 @@ +{ + "name": "abbrev", + "version": "1.0.4", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/abbrev-js/issues" + }, + "_id": "abbrev@1.0.4", + "_from": "abbrev@1" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json new file mode 100644 index 000000000..3bc4490d7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json @@ -0,0 +1,39 @@ +{ + "name": "nopt", + "version": "2.0.0", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/nopt/issues" + }, + "_id": "nopt@2.0.0", + "dist": { + "shasum": "8f389ee5984f4af06ba5dd72d8c41583ca0b59f2" + }, + "_from": "nopt@~2.0.0", + "_resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json new file mode 100644 index 000000000..5b953b656 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json @@ -0,0 +1,32 @@ +{ + "author": { + "name": "mklabs" + }, + "name": "noptify", + "description": "nopt wrapper with commander-like API", + "version": "0.0.3", + "repository": { + "type": "git", + "url": "git://github.com/mklabs/noptify.git" + }, + "dependencies": { + "nopt": "~2.0.0" + }, + "devDependencies": { + "mocha": "~1.8.1" + }, + "scripts": { + "test": "mocha --reporter spec" + }, + "readme": "### noptify\n\nnoptify is a little wrapper around `nopt` module adding a more expressive,\ncommander-like, API and few helpers.\n\nExamples\n\n var program = noptify(process.argv, { program: 'name' })\n .version('0.0.1')\n .option('port', '-p', 'Port to listen on (default: 35729)', Number)\n .option('pid', 'Path to the generated PID file', String)\n\n var opts = program.parse();\n\nReturns an instance of `Noptify`\n\n### Noptify\n\nNoptify provides the API to parse out option, shorthands and generate the\nproper generic help output.\n\n- args - The Array of arguments to parse (default: `process.argv`);\n- options - An hash of options with the following properties\n - program - The program name to use in usage output\n\nEvery noptify instance is created with two options, `-h, --help` and `-v,\n--version`.\n\n### Noptify#parse\n\nParse the provided options and shorthands, pass them through `nopt` and\nreturn the result.\n\nWhen `opts.help` is set, the help output is displayed and `help`\nevent is emitted. The process exists with `0` status, the help output is\nautomatically displayed and the `help` event is emitted.\n\nExamples\n\n var program = noptify(['foo', '--help'])\n .on('help', function() {\n console.log('Examples');\n console.log('');\n console.log(' foo bar --baz > foo.txt');\n });\n\n var opts = program.parse();\n // ... Help output ...\n // ... Custom help output ...\n // ... Exit ...\n\n\n\n### Noptify#version\n\nDefine the program version.\n\n### Noptify#option\n\nDefine `name` option with optional shorthands, optional description and optional type.\n\n### Noptify#help\n\nSimply output to stdout the Usage and Help output.\n\n---\n\n*Mocha generated documentation*\n\n- [API](#api)\n- [Collectable](#collectable)\n- [Commandable](#commandable)\n - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command)\n\n\n\n\n## API\nreturns an instanceof Noptify.\n\n```js\nassert.ok(noptify() instanceof noptify.Noptify);\n```\n\nis typically used like so.\n\n```js\nvar program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'])\n .option('debug', '-d', 'Enabled debug output', Boolean)\n .option('dirname', 'The path to the output directory')\n .option('port', '-p', 'The port you wish to listen on', Number)\n\n// opts => nopt result\nvar opts = program.parse();\n\nassert.deepEqual(opts, {\n port: 3000,\n debug: true,\n dirname: './',\n argv: {\n remain: ['app.js', 'base.js'],\n cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'],\n original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']\n }\n});\n```\n\nallows definitiion of shorthands separately.\n\n```js\nvar opts = noptify(['node', 'file.js', '-lc'])\n .option('line-comment', 'Ouputs with debugging information', Boolean)\n .shorthand('lc', '--line-comment')\n .parse();\n\nassert.equal(opts['line-comment'], true);\n```\n\n\n## Collectable\nprovides the helper method to read from stdin.\n\n```js\nvar program = noptify();\nassert.ok(typeof program.stdin === 'function', 'stdin defined');\n```\n\nis invoked only when .parse() is called.\n\n```js\nvar program = noptify(['', '']);\nvar str = 'testing out stdin helper';\nprogram.stdin(function(err, res) {\n assert.equal(res, str);\n done();\n});\n\nprogram.parse();\n\nprocess.nextTick(function() {\n process.stdin.emit('data', str);\n process.stdin.emit('end');\n});\n```\n\n\n## Commandable\nprovides the .command() utility.\n\n```js\nassert.ok(typeof noptify().command === 'function');\n```\n\n\n## Parses remaining arguments and route to the appropriate command\ncan be a simple function.\n\n```js\nvar program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option');\n\nprogram.command('init', function(args, opts) {\n // args ==> sliced args at command position\n // opts ==> nopt parsed object\n assert.deepEqual(args, ['--debug', 'foo']);\n assert.equal(opts.debug, true);\n assert.equal(opts.argv.remain[0], 'foo');\n done();\n});\n\nprogram.parse();\n```\n\nor another program, an Noptify instance.\n\n```js\nvar args = ['', '', 'init', '--debug', 'myapp', 'foo'];\n\nvar init = noptify(args)\n .option('debug', 'Debug output')\n .command('myapp', done.bind(null, null));\n\nnoptify(args).command('init', init).parse();\n```\n\n", + "readmeFilename": "readme.md", + "bugs": { + "url": "https://github.com/mklabs/noptify/issues" + }, + "_id": "noptify@0.0.3", + "dist": { + "shasum": "4a3dcc99dd83806bef26a52eaf301fe13902e8c1" + }, + "_from": "noptify@latest", + "_resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md new file mode 100644 index 000000000..6e41adbff --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md @@ -0,0 +1,184 @@ +### noptify + +noptify is a little wrapper around `nopt` module adding a more expressive, +commander-like, API and few helpers. + +Examples + + var program = noptify(process.argv, { program: 'name' }) + .version('0.0.1') + .option('port', '-p', 'Port to listen on (default: 35729)', Number) + .option('pid', 'Path to the generated PID file', String) + + var opts = program.parse(); + +Returns an instance of `Noptify` + +### Noptify + +Noptify provides the API to parse out option, shorthands and generate the +proper generic help output. + +- args - The Array of arguments to parse (default: `process.argv`); +- options - An hash of options with the following properties + - program - The program name to use in usage output + +Every noptify instance is created with two options, `-h, --help` and `-v, +--version`. + +### Noptify#parse + +Parse the provided options and shorthands, pass them through `nopt` and +return the result. + +When `opts.help` is set, the help output is displayed and `help` +event is emitted. The process exists with `0` status, the help output is +automatically displayed and the `help` event is emitted. + +Examples + + var program = noptify(['foo', '--help']) + .on('help', function() { + console.log('Examples'); + console.log(''); + console.log(' foo bar --baz > foo.txt'); + }); + + var opts = program.parse(); + // ... Help output ... + // ... Custom help output ... + // ... Exit ... + + + +### Noptify#version + +Define the program version. + +### Noptify#option + +Define `name` option with optional shorthands, optional description and optional type. + +### Noptify#help + +Simply output to stdout the Usage and Help output. + +--- + +*Mocha generated documentation* + +- [API](#api) +- [Collectable](#collectable) +- [Commandable](#commandable) + - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command) + + + + +## API +returns an instanceof Noptify. + +```js +assert.ok(noptify() instanceof noptify.Noptify); +``` + +is typically used like so. + +```js +var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']) + .option('debug', '-d', 'Enabled debug output', Boolean) + .option('dirname', 'The path to the output directory') + .option('port', '-p', 'The port you wish to listen on', Number) + +// opts => nopt result +var opts = program.parse(); + +assert.deepEqual(opts, { + port: 3000, + debug: true, + dirname: './', + argv: { + remain: ['app.js', 'base.js'], + cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'], + original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'] + } +}); +``` + +allows definitiion of shorthands separately. + +```js +var opts = noptify(['node', 'file.js', '-lc']) + .option('line-comment', 'Ouputs with debugging information', Boolean) + .shorthand('lc', '--line-comment') + .parse(); + +assert.equal(opts['line-comment'], true); +``` + + +## Collectable +provides the helper method to read from stdin. + +```js +var program = noptify(); +assert.ok(typeof program.stdin === 'function', 'stdin defined'); +``` + +is invoked only when .parse() is called. + +```js +var program = noptify(['', '']); +var str = 'testing out stdin helper'; +program.stdin(function(err, res) { + assert.equal(res, str); + done(); +}); + +program.parse(); + +process.nextTick(function() { + process.stdin.emit('data', str); + process.stdin.emit('end'); +}); +``` + + +## Commandable +provides the .command() utility. + +```js +assert.ok(typeof noptify().command === 'function'); +``` + + +## Parses remaining arguments and route to the appropriate command +can be a simple function. + +```js +var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option'); + +program.command('init', function(args, opts) { + // args ==> sliced args at command position + // opts ==> nopt parsed object + assert.deepEqual(args, ['--debug', 'foo']); + assert.equal(opts.debug, true); + assert.equal(opts.argv.remain[0], 'foo'); + done(); +}); + +program.parse(); +``` + +or another program, an Noptify instance. + +```js +var args = ['', '', 'init', '--debug', 'myapp', 'foo']; + +var init = noptify(args) + .option('debug', 'Debug output') + .command('myapp', done.bind(null, null)); + +noptify(args).command('init', init).parse(); +``` + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js new file mode 100644 index 000000000..e02285091 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js @@ -0,0 +1,53 @@ +var noptify = require('..'); +var assert = require('assert'); + +describe('API', function() { + + it('returns an instanceof Noptify', function() { + assert.ok(noptify() instanceof noptify.Noptify); + }); + + + it('is typically used like so', function() { + var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']) + .option('debug', '-d', 'Enabled debug output', Boolean) + .option('dirname', 'The path to the output directory') + .option('port', '-p', 'The port you wish to listen on', Number) + + // opts => nopt result + var opts = program.parse(); + + assert.deepEqual(opts, { + port: 3000, + debug: true, + dirname: './', + argv: { + remain: ['app.js', 'base.js'], + cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'], + original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'] + } + }); + }); + + it('allows definitiion of shorthands separately', function() { + var opts = noptify(['node', 'file.js', '-lc']) + .option('line-comment', 'Ouputs with debugging information', Boolean) + .shorthand('lc', '--line-comment') + .parse(); + + assert.equal(opts['line-comment'], true); + }); + + // hmm, keep this one for the very last, or do another way, process exit + // prevent other tests from running + it.skip('outputs help and exit the process with --help', function() { + var program = noptify(['', '', '--help']) + assert.throws(function() { + throw new Error('parse() must be called for this to happen'); + }); + + program.parse(); + throw new Error('I\'m sad, I\'ll never throw :('); + }); + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js new file mode 100644 index 000000000..02d578ab4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js @@ -0,0 +1,40 @@ +var noptify = require('..'); +var assert = require('assert'); + + +describe('Collectable', function() { + + it('provides the helper method to read from stdin', function() { + var program = noptify(); + assert.ok(typeof program.stdin === 'function', 'stdin defined'); + }); + + it('is invoked only when .parse() is called', function(done) { + var program = noptify(['', '']); + var str = 'testing out stdin helper'; + program.stdin(function(err, res) { + assert.equal(res, str); + done(); + }); + + program.parse(); + + process.nextTick(function() { + process.stdin.emit('data', str); + process.stdin.emit('end'); + }); + }); + + + it('.files()', function(done) { + var program = noptify(['', '', 'test/fixtures/a.js', 'test/fixtures/b.js']); + program.parse(); + + program.files(function(err, data) { + assert.equal(data, 'a\nb\n'); + done(); + }); + + }); + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js new file mode 100644 index 000000000..39610f7ab --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js @@ -0,0 +1,40 @@ +var noptify = require('..'); +var assert = require('assert'); + +describe('Commandable', function() { + + it('provides the .command() utility', function() { + assert.ok(typeof noptify().command === 'function'); + }); + + + describe('Parses remaining arguments and route to the appropriate command', function() { + + it('can be a simple function', function(done) { + var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option'); + + program.command('init', function(args, opts) { + // args ==> sliced args at command position + // opts ==> nopt parsed object + assert.deepEqual(args, ['--debug', 'foo']); + assert.equal(opts.debug, true); + assert.equal(opts.argv.remain[0], 'foo'); + done(); + }); + + program.parse(); + }); + + it('or another program, an Noptify instance', function(done) { + var args = ['', '', 'init', '--debug', 'myapp', 'foo']; + + var init = noptify(args) + .option('debug', 'Debug output') + .command('myapp', done.bind(null, null)); + + noptify(args).command('init', init).parse(); + }); + }); + + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js new file mode 100644 index 000000000..789819226 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js @@ -0,0 +1 @@ +a diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js new file mode 100644 index 000000000..617807982 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js @@ -0,0 +1 @@ +b diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js new file mode 100644 index 000000000..d7e717ca2 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js @@ -0,0 +1,15 @@ + + +// Simple extend utility method + +module.exports = function extend(obj) { + var args = Array.prototype.slice.call(arguments, 1); + + args.forEach(function(o) { + Object.keys(o).forEach(function(prop) { + obj[prop] = o[prop]; + }); + }); + + return obj; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js new file mode 100644 index 000000000..115ead580 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js @@ -0,0 +1,6 @@ + +// Common interface to utility methods, exposing the standard `util` core module +var util = module.exports = require('util'); + +// and augmenting it +util.extend = require('./extend'); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules new file mode 100644 index 000000000..49e31dac7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml new file mode 100644 index 000000000..2c0a8f63f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.4 \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md new file mode 100644 index 000000000..c9a0e3c5f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md @@ -0,0 +1,109 @@ + +0.5.6 / 2013-04-09 +================== + + * fix empty key productions in parser + +0.5.5 / 2013-03-20 +================== + + * output key= for null or undefined values. Closes #52 + +0.5.4 / 2013-03-15 +================== + + * fix ignoring of null / undefined. Closes #44 + +0.5.3 2012-12-09 +================== + + * add info to component.json + * remove regular client-side ./querystring.js, fix component.json support + +0.5.2 / 2012-11-14 +================== + + * fix uri encoding of non-plain object string values + +0.5.1 / 2012-09-18 +================== + + * fix encoded `=`. Closes #43 + +0.5.0 / 2012-05-04 +================== + + * Added component support + +0.4.2 / 2012-02-08 +================== + + * Fixed: ensure objects are created when appropriate not arrays [aheckmann] + +0.4.1 / 2012-01-26 +================== + + * Fixed stringify()ing numbers. Closes #23 + +0.4.0 / 2011-11-21 +================== + + * Allow parsing of an existing object (for `bodyParser()`) [jackyz] + * Replaced expresso with mocha + +0.3.2 / 2011-11-08 +================== + + * Fixed global variable leak + +0.3.1 / 2011-08-17 +================== + + * Added `try/catch` around malformed uri components + * Add test coverage for Array native method bleed-though + +0.3.0 / 2011-07-19 +================== + + * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart] + +0.2.0 / 2011-06-29 +================== + + * Added `qs.stringify()` [Cory Forsyth] + +0.1.0 / 2011-04-13 +================== + + * Added jQuery-ish array support + +0.0.7 / 2011-03-13 +================== + + * Fixed; handle empty string and `== null` in `qs.parse()` [dmit] + allows for convenient `qs.parse(url.parse(str).query)` + +0.0.6 / 2011-02-14 +================== + + * Fixed; support for implicit arrays + +0.0.4 / 2011-02-09 +================== + + * Fixed `+` as a space + +0.0.3 / 2011-02-08 +================== + + * Fixed case when right-hand value contains "]" + +0.0.2 / 2011-02-07 +================== + + * Fixed "=" presence in key + +0.0.1 / 2011-02-07 +================== + + * Initial release diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile new file mode 100644 index 000000000..84a78ec18 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile @@ -0,0 +1,6 @@ + +test: + @./node_modules/.bin/mocha \ + --ui bdd + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md new file mode 100644 index 000000000..27e54a4af --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js new file mode 100644 index 000000000..97e2c93ed --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js @@ -0,0 +1,17 @@ + +var qs = require('./'); + +var times = 100000 + , start = new Date + , n = times; + +console.log('times: %d', times); + +while (n--) qs.parse('foo=bar'); +console.log('simple: %dms', new Date - start); + +var start = new Date + , n = times; + +while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log('nested: %dms', new Date - start); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json new file mode 100644 index 000000000..0a46c2d4e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json @@ -0,0 +1,9 @@ +{ + "name": "querystring", + "repo": "visionmedia/node-querystring", + "description": "query-string parser / stringifier with nesting support", + "version": "0.5.6", + "keywords": ["querystring", "query", "parser"], + "scripts": ["index.js"], + "license": "MIT" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js new file mode 100644 index 000000000..ebe3a97a4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js @@ -0,0 +1,51 @@ + +/** + * Module dependencies. + */ + +var qs = require('./'); + +var obj = qs.parse('foo'); +console.log(obj) + +var obj = qs.parse('foo=bar=baz'); +console.log(obj) + +var obj = qs.parse('users[]'); +console.log(obj) + +var obj = qs.parse('name=tj&email=tj@vision-media.ca'); +console.log(obj) + +var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('a=a&a=b&a=c'); +console.log(obj) + +var obj = qs.parse('user[tj]=tj&user[tj]=TJ'); +console.log(obj) + +var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[1]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[foo]=TJ'); +console.log(obj) + +var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}); +console.log(str); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js new file mode 100644 index 000000000..8b27b2387 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js @@ -0,0 +1,268 @@ + +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = {}; + var t = {}; + for (var i in parent[key]) t[i] = parent[key][i]; + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (Array.isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (Array.isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[Object.keys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~part.indexOf(']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~key.indexOf(']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && Array.isArray(parent.base)) { + var t = {}; + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + Object.keys(obj).forEach(function(name){ + merge(ret, name, obj[name]); + }); + return ret.base; +} + +/** + * Parse the given str. + */ + +function parseString(str){ + return String(str) + .split('&') + .reduce(function(ret, pair){ + var eql = pair.indexOf('=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(val.indexOf('=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: {} }).base; +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (Array.isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = Object.keys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (Array.isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json new file mode 100644 index 000000000..f17abab49 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json @@ -0,0 +1,43 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.5.6", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "component": { + "scripts": { + "querystring": "querystring.js" + } + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/node-querystring/issues" + }, + "_id": "qs@0.5.6", + "dist": { + "shasum": "aa102f78b4077462786332916d29184b897ac228" + }, + "_from": "qs@~0.5.2", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js new file mode 100644 index 000000000..76aa4e84f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js @@ -0,0 +1,1202 @@ + +(function (global, module) { + + if ('undefined' == typeof module) { + var module = { exports: {} } + , exports = module.exports + } + + /** + * Exports. + */ + + module.exports = expect; + expect.Assertion = Assertion; + + /** + * Exports version. + */ + + expect.version = '0.1.2'; + + /** + * Possible assertion flags. + */ + + var flags = { + not: ['to', 'be', 'have', 'include', 'only'] + , to: ['be', 'have', 'include', 'only', 'not'] + , only: ['have'] + , have: ['own'] + , be: ['an'] + }; + + function expect (obj) { + return new Assertion(obj); + } + + /** + * Constructor + * + * @api private + */ + + function Assertion (obj, flag, parent) { + this.obj = obj; + this.flags = {}; + + if (undefined != parent) { + this.flags[flag] = true; + + for (var i in parent.flags) { + if (parent.flags.hasOwnProperty(i)) { + this.flags[i] = true; + } + } + } + + var $flags = flag ? flags[flag] : keys(flags) + , self = this + + if ($flags) { + for (var i = 0, l = $flags.length; i < l; i++) { + // avoid recursion + if (this.flags[$flags[i]]) continue; + + var name = $flags[i] + , assertion = new Assertion(this.obj, name, this) + + if ('function' == typeof Assertion.prototype[name]) { + // clone the function, make sure we dont touch the prot reference + var old = this[name]; + this[name] = function () { + return old.apply(self, arguments); + } + + for (var fn in Assertion.prototype) { + if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { + this[name][fn] = bind(assertion[fn], assertion); + } + } + } else { + this[name] = assertion; + } + } + } + }; + + /** + * Performs an assertion + * + * @api private + */ + + Assertion.prototype.assert = function (truth, msg, error) { + var msg = this.flags.not ? error : msg + , ok = this.flags.not ? !truth : truth; + + if (!ok) { + throw new Error(msg); + } + + this.and = new Assertion(this.obj); + }; + + /** + * Check if the value is truthy + * + * @api public + */ + + Assertion.prototype.ok = function () { + this.assert( + !!this.obj + , 'expected ' + i(this.obj) + ' to be truthy' + , 'expected ' + i(this.obj) + ' to be falsy'); + }; + + /** + * Assert that the function throws. + * + * @param {Function|RegExp} callback, or regexp to match error string against + * @api public + */ + + Assertion.prototype.throwError = + Assertion.prototype.throwException = function (fn) { + expect(this.obj).to.be.a('function'); + + var thrown = false + , not = this.flags.not + + try { + this.obj(); + } catch (e) { + if ('function' == typeof fn) { + fn(e); + } else if ('object' == typeof fn) { + var subject = 'string' == typeof e ? e : e.message; + if (not) { + expect(subject).to.not.match(fn); + } else { + expect(subject).to.match(fn); + } + } + thrown = true; + } + + if ('object' == typeof fn && not) { + // in the presence of a matcher, ensure the `not` only applies to + // the matching. + this.flags.not = false; + } + + var name = this.obj.name || 'fn'; + this.assert( + thrown + , 'expected ' + name + ' to throw an exception' + , 'expected ' + name + ' not to throw an exception'); + }; + + /** + * Checks if the array is empty. + * + * @api public + */ + + Assertion.prototype.empty = function () { + var expectation; + + if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { + if ('number' == typeof this.obj.length) { + expectation = !this.obj.length; + } else { + expectation = !keys(this.obj).length; + } + } else { + if ('string' != typeof this.obj) { + expect(this.obj).to.be.an('object'); + } + + expect(this.obj).to.have.property('length'); + expectation = !this.obj.length; + } + + this.assert( + expectation + , 'expected ' + i(this.obj) + ' to be empty' + , 'expected ' + i(this.obj) + ' to not be empty'); + return this; + }; + + /** + * Checks if the obj exactly equals another. + * + * @api public + */ + + Assertion.prototype.be = + Assertion.prototype.equal = function (obj) { + this.assert( + obj === this.obj + , 'expected ' + i(this.obj) + ' to equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to not equal ' + i(obj)); + return this; + }; + + /** + * Checks if the obj sortof equals another. + * + * @api public + */ + + Assertion.prototype.eql = function (obj) { + this.assert( + expect.eql(obj, this.obj) + , 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj)); + return this; + }; + + /** + * Assert within start to finish (inclusive). + * + * @param {Number} start + * @param {Number} finish + * @api public + */ + + Assertion.prototype.within = function (start, finish) { + var range = start + '..' + finish; + this.assert( + this.obj >= start && this.obj <= finish + , 'expected ' + i(this.obj) + ' to be within ' + range + , 'expected ' + i(this.obj) + ' to not be within ' + range); + return this; + }; + + /** + * Assert typeof / instance of + * + * @api public + */ + + Assertion.prototype.a = + Assertion.prototype.an = function (type) { + if ('string' == typeof type) { + // proper english in error msg + var n = /^[aeiou]/.test(type) ? 'n' : ''; + + // typeof with support for 'array' + this.assert( + 'array' == type ? isArray(this.obj) : + 'object' == type + ? 'object' == typeof this.obj && null !== this.obj + : type == typeof this.obj + , 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type + , 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type); + } else { + // instanceof + var name = type.name || 'supplied constructor'; + this.assert( + this.obj instanceof type + , 'expected ' + i(this.obj) + ' to be an instance of ' + name + , 'expected ' + i(this.obj) + ' not to be an instance of ' + name); + } + + return this; + }; + + /** + * Assert numeric value above _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.greaterThan = + Assertion.prototype.above = function (n) { + this.assert( + this.obj > n + , 'expected ' + i(this.obj) + ' to be above ' + n + , 'expected ' + i(this.obj) + ' to be below ' + n); + return this; + }; + + /** + * Assert numeric value below _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.lessThan = + Assertion.prototype.below = function (n) { + this.assert( + this.obj < n + , 'expected ' + i(this.obj) + ' to be below ' + n + , 'expected ' + i(this.obj) + ' to be above ' + n); + return this; + }; + + /** + * Assert string value matches _regexp_. + * + * @param {RegExp} regexp + * @api public + */ + + Assertion.prototype.match = function (regexp) { + this.assert( + regexp.exec(this.obj) + , 'expected ' + i(this.obj) + ' to match ' + regexp + , 'expected ' + i(this.obj) + ' not to match ' + regexp); + return this; + }; + + /** + * Assert property "length" exists and has value of _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.length = function (n) { + expect(this.obj).to.have.property('length'); + var len = this.obj.length; + this.assert( + n == len + , 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len + , 'expected ' + i(this.obj) + ' to not have a length of ' + len); + return this; + }; + + /** + * Assert property _name_ exists, with optional _val_. + * + * @param {String} name + * @param {Mixed} val + * @api public + */ + + Assertion.prototype.property = function (name, val) { + if (this.flags.own) { + this.assert( + Object.prototype.hasOwnProperty.call(this.obj, name) + , 'expected ' + i(this.obj) + ' to have own property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have own property ' + i(name)); + return this; + } + + if (this.flags.not && undefined !== val) { + if (undefined === this.obj[name]) { + throw new Error(i(this.obj) + ' has no property ' + i(name)); + } + } else { + var hasProp; + try { + hasProp = name in this.obj + } catch (e) { + hasProp = undefined !== this.obj[name] + } + + this.assert( + hasProp + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name)); + } + + if (undefined !== val) { + this.assert( + val === this.obj[name] + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + + ' of ' + i(val) + ', but got ' + i(this.obj[name]) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name) + + ' of ' + i(val)); + } + + this.obj = this.obj[name]; + return this; + }; + + /** + * Assert that the array contains _obj_ or string contains _obj_. + * + * @param {Mixed} obj|string + * @api public + */ + + Assertion.prototype.string = + Assertion.prototype.contain = function (obj) { + if ('string' == typeof this.obj) { + this.assert( + ~this.obj.indexOf(obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } else { + this.assert( + ~indexOf(this.obj, obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } + return this; + }; + + /** + * Assert exact keys or inclusion of keys by using + * the `.own` modifier. + * + * @param {Array|String ...} keys + * @api public + */ + + Assertion.prototype.key = + Assertion.prototype.keys = function ($keys) { + var str + , ok = true; + + $keys = isArray($keys) + ? $keys + : Array.prototype.slice.call(arguments); + + if (!$keys.length) throw new Error('keys required'); + + var actual = keys(this.obj) + , len = $keys.length; + + // Inclusion + ok = every($keys, function (key) { + return ~indexOf(actual, key); + }); + + // Strict + if (!this.flags.not && this.flags.only) { + ok = ok && $keys.length == actual.length; + } + + // Key string + if (len > 1) { + $keys = map($keys, function (key) { + return i(key); + }); + var last = $keys.pop(); + str = $keys.join(', ') + ', and ' + last; + } else { + str = i($keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (!this.flags.only ? 'include ' : 'only have ') + str; + + // Assertion + this.assert( + ok + , 'expected ' + i(this.obj) + ' to ' + str + , 'expected ' + i(this.obj) + ' to not ' + str); + + return this; + }; + + /** + * Function bind implementation. + */ + + function bind (fn, scope) { + return function () { + return fn.apply(scope, arguments); + } + } + + /** + * Array every compatibility + * + * @see bit.ly/5Fq1N2 + * @api public + */ + + function every (arr, fn, thisObj) { + var scope = thisObj || global; + for (var i = 0, j = arr.length; i < j; ++i) { + if (!fn.call(scope, arr[i], i, arr)) { + return false; + } + } + return true; + }; + + /** + * Array indexOf compatibility. + * + * @see bit.ly/a5Dxa2 + * @api public + */ + + function indexOf (arr, o, i) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(arr, o, i); + } + + if (arr.length === undefined) { + return -1; + } + + for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 + ; i < j && arr[i] !== o; i++); + + return j <= i ? -1 : i; + }; + + /** + * Inspects an object. + * + * @see taken from node.js `util` module (copyright Joyent, MIT license) + * @api private + */ + + function i (obj, showHidden, depth) { + var seen = []; + + function stylize (str) { + return str; + }; + + function format (value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value !== exports && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + return value.inspect(recurseTimes); + } + + // Primitive types cannot have properties + switch (typeof value) { + case 'undefined': + return stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return stylize(simple, 'string'); + + case 'number': + return stylize('' + value, 'number'); + + case 'boolean': + return stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return stylize('null', 'null'); + } + + // Look up the keys of the object. + var visible_keys = keys(value); + var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; + + // Functions without properties can be shortcutted. + if (typeof value === 'function' && $keys.length === 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + var name = value.name ? ': ' + value.name : ''; + return stylize('[Function' + name + ']', 'special'); + } + } + + // Dates without properties can be shortcutted + if (isDate(value) && $keys.length === 0) { + return stylize(value.toUTCString(), 'date'); + } + + var base, type, braces; + // Determine the object type + if (isArray(value)) { + type = 'Array'; + braces = ['[', ']']; + } else { + type = 'Object'; + braces = ['{', '}']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var n = value.name ? ': ' + value.name : ''; + base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; + } else { + base = ''; + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + value.toUTCString(); + } + + if ($keys.length === 0) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + return stylize('[Object]', 'special'); + } + } + + seen.push(value); + + var output = map($keys, function (key) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = stylize('[Getter/Setter]', 'special'); + } else { + str = stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = stylize('[Setter]', 'special'); + } + } + } + if (indexOf(visible_keys, key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (indexOf(seen, value[key]) < 0) { + if (recurseTimes === null) { + str = format(value[key]); + } else { + str = format(value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (isArray(value)) { + str = map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (type === 'Array' && key.match(/^\d+$/)) { + return str; + } + name = json.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = stylize(name, 'string'); + } + } + + return name + ': ' + str; + }); + + seen.pop(); + + var numLinesEst = 0; + var length = reduce(output, function (prev, cur) { + numLinesEst++; + if (indexOf(cur, '\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 50) { + output = braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + + } else { + output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + return output; + } + return format(obj, (typeof depth === 'undefined' ? 2 : depth)); + }; + + function isArray (ar) { + return Object.prototype.toString.call(ar) == '[object Array]'; + }; + + function isRegExp(re) { + var s = '' + re; + return re instanceof RegExp || // easy case + // duck-type for context-switching evalcx case + typeof(re) === 'function' && + re.constructor.name === 'RegExp' && + re.compile && + re.test && + re.exec && + s.match(/^\/.*\/[gim]{0,3}$/); + }; + + function isDate(d) { + if (d instanceof Date) return true; + return false; + }; + + function keys (obj) { + if (Object.keys) { + return Object.keys(obj); + } + + var keys = []; + + for (var i in obj) { + if (Object.prototype.hasOwnProperty.call(obj, i)) { + keys.push(i); + } + } + + return keys; + } + + function map (arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other= new Array(arr.length); + + for (var i= 0, n = arr.length; i= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= len) + throw new TypeError(); + } while (true); + } + + for (; i < len; i++) { + if (i in this) + rv = fun.call(null, rv, this[i], i, this); + } + + return rv; + }; + + /** + * Asserts deep equality + * + * @see taken from node.js `assert` module (copyright Joyent, MIT license) + * @api private + */ + + expect.eql = function eql (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if ('undefined' != typeof Buffer + && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } + } + + function isUndefinedOrNull (value) { + return value === null || value === undefined; + } + + function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; + } + + function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return expect.eql(a, b); + } + try{ + var ka = keys(a), + kb = keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!expect.eql(a[key], b[key])) + return false; + } + return true; + } + + var json = (function () { + "use strict"; + + if ('object' == typeof JSON && JSON.parse && JSON.stringify) { + return { + parse: nativeJSON.parse + , stringify: nativeJSON.stringify + } + } + + var JSON = {}; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + function date(d, key) { + return isFinite(d.valueOf()) ? + d.getUTCFullYear() + '-' + + f(d.getUTCMonth() + 1) + '-' + + f(d.getUTCDate()) + 'T' + + f(d.getUTCHours()) + ':' + + f(d.getUTCMinutes()) + ':' + + f(d.getUTCSeconds()) + 'Z' : null; + }; + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + + // Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + + if (value instanceof Date) { + value = date(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + + // JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + + return String(value); + + // If the type is 'object', we might be dealing with an object or an array or + // null. + + case 'object': + + // Due to a specification blunder in ECMAScript, typeof null is 'object', + // so watch out for that case. + + if (!value) { + return 'null'; + } + + // Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + + // Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + + // The value is an array. Stringify every element. Use null as a placeholder + // for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and wrap them in + // brackets. + + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + + // Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + + // If the JSON object does not yet have a stringify method, give it one. + + JSON.stringify = function (value, replacer, space) { + + // The stringify method takes a value and an optional replacer, and an optional + // space parameter, and returns a JSON text. The replacer can be a function + // that can replace values, or an array of strings that will select the keys. + // A default replacer method can be provided. Use of the space parameter can + // produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + + // If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + + return str('', {'': value}); + }; + + // If the JSON object does not yet have a parse method, give it one. + + JSON.parse = function (text, reviver) { + // The parse method takes a text and an optional reviver function, and returns + // a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + + // The walk method is used to recursively walk the resulting structure so + // that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + + // Parsing happens in four stages. In the first stage, we replace certain + // Unicode characters with escape sequences. JavaScript handles many characters + // incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + + // In the second stage, we run the text against regular expressions that look + // for non-JSON patterns. We are especially concerned with '()' and 'new' + // because they can cause invocation, and '=' because it can cause mutation. + // But just to be safe, we want to reject all unexpected forms. + + // We split the second stage into 4 regexp operations in order to work around + // crippling inefficiencies in IE's and Safari's regexp engines. First we + // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we + // replace all simple value tokens with ']' characters. Third, we delete all + // open brackets that follow a colon or comma or that begin the text. Finally, + // we look to see that the remaining characters are only whitespace or ']' or + // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + // In the third stage we use the eval function to compile the text into a + // JavaScript structure. The '{' operator is subject to a syntactic ambiguity + // in JavaScript: it can begin a block or an object literal. We wrap the text + // in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + + // In the optional fourth stage, we recursively walk the new structure, passing + // each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + + // If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + + return JSON; + })(); + + if ('undefined' != typeof window) { + window.expect = module.exports; + } + +})( + this + , 'undefined' != typeof module ? module : {} + , 'undefined' != typeof exports ? exports : {} +); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html new file mode 100644 index 000000000..c73147aaa --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html @@ -0,0 +1,18 @@ + + + Mocha + + + + + + + + + + + + +
      + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js new file mode 100644 index 000000000..f3201aacb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js @@ -0,0 +1,8981 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z])/ig, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Converts a dashed string to camelCased string; + // Used by both the css and data modules + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
      a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0 + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: -1000, + top: -1000 + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
      "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
      t
      "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? + // Check for both converted-to-camel and non-converted data property names + thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : + thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:|^on/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && name !== "className" && + (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + + hooks = formHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + }, + // Use the value property for back compat + // Use the formHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return jQuery.prop( elem, name ) ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

      "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
      "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
      ", "
      " ], + thead: [ 1, "", "
      " ], + tr: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + col: [ 2, "", "
      " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and \n```\n\nFeel free to add this script to your template situation and toggle with some sort of `dev` flag.\n\n##### Using Live Reload with the Browser Extension\nInstead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser.\n\nOnce installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the ` + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + ); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ], function (err, result) { + // result now equals 'done' + }); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + // add some items to the queue (batch-wise) + + q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. If all tasks complete + successfully, it will receive an object containing their results. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/grunt/node_modules/async/index.js b/node_modules/grunt/node_modules/async/index.js new file mode 100644 index 000000000..8e238453e --- /dev/null +++ b/node_modules/grunt/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/node_modules/grunt/node_modules/async/lib/async.js b/node_modules/grunt/node_modules/async/lib/async.js new file mode 100644 index 000000000..7cc4f5eac --- /dev/null +++ b/node_modules/grunt/node_modules/async/lib/async.js @@ -0,0 +1,692 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _forEach(data, function(task) { + q.tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (q.saturated && q.tasks.length == concurrency) { + q.saturated(); + } + async.nextTick(q.process); + }); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + +}()); diff --git a/node_modules/grunt/node_modules/async/package.json b/node_modules/grunt/node_modules/async/package.json new file mode 100644 index 000000000..4ac17961a --- /dev/null +++ b/node_modules/grunt/node_modules/async/package.json @@ -0,0 +1,35 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "./index", + "author": { + "name": "Caolan McMahon" + }, + "version": "0.1.22", + "repository": { + "type": "git", + "url": "http://github.com/caolan/async.git" + }, + "bugs": { + "url": "http://github.com/caolan/async/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/async/raw/master/LICENSE" + } + ], + "devDependencies": { + "nodeunit": ">0.0.0", + "uglify-js": "1.2.x", + "nodelint": ">0.0.0" + }, + "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser.\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, forEach…) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfall…). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n async.parallel([\n function(){ ... },\n function(){ ... }\n ], callback);\n\n async.series([\n function(){ ... },\n function(){ ... }\n ]);\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n\n## Download\n\nReleases are available for download from\n[GitHub](http://github.com/caolan/async/downloads).\nAlternatively, you can install using Node Package Manager (npm):\n\n npm install async\n\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed\n\n__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped\n\n\n## In the Browser\n\nSo far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n \n \n\n\n## Documentation\n\n### Collections\n\n* [forEach](#forEach)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [until](#until)\n* [waterfall](#waterfall)\n* [queue](#queue)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n### forEach(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the forEach function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // assuming openFiles is an array of file names and saveFile is a function\n // to save the modified contents of that file:\n\n async.forEach(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n\n---------------------------------------\n\n\n### forEachSeries(arr, iterator, callback)\n\nThe same as forEach only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n### forEachLimit(arr, limit, iterator, callback)\n\nThe same as forEach only the iterator is applied to batches of items in the\narray, in series. The next batch of iterators is only called once the current\none has completed processing.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - How many items should be in each batch.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // Assume documents is an array of JSON objects and requestApi is a\n // function that interacts with a rate-limited REST api.\n\n async.forEachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as filter, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then its probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback which accepts an optional error as its first argument, and the state\n of the reduction as the second. If an error is passed to the callback, the\n reduction is stopped and the main callback is immediately called with the\n error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n async.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n }, function(err, result){\n // result is now equal to the last value of memo, which is 6\n });\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n async.detect(['file1','file2','file3'], path.exists, function(result){\n // result now equals the first file in the list that exists\n });\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a value to use as the sort criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n async.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n }, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n });\n\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n async.some(['file1','file2','file3'], path.exists, function(result){\n // if result is true then at least one of the files exists\n });\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n async.every(['file1','file2','file3'], path.exists, function(result){\n // if result is true then every file exists\n });\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n });\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n },\n ],\n // optional callback\n function(err, results){\n // results is now equal to ['one', 'two']\n });\n\n\n // an example using an object instead of an array\n async.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equal to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed a\n callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n },\n ],\n // optional callback\n function(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n });\n\n\n // an example using an object instead of an array\n async.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equals to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback which must be called once it has completed with an optional\n error as the first argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n var count = 0;\n\n async.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n );\n\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n async.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n ], function (err, result) {\n // result now equals 'done' \n });\n\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n // create a queue object with concurrency 2\n\n var q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n }, 2);\n\n\n // assign a callback\n q.drain = function() {\n console.log('all items have been processed');\n }\n\n // add some items to the queue\n\n q.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n });\n q.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n });\n\n // add some items to the queue (batch-wise)\n\n q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n });\n\n\n---------------------------------------\n\n\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The\n syntax is easier to understand by looking at the example.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. If all tasks complete\n successfully, it will receive an object containing their results.\n\n__Example__\n\n async.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n });\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n async.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n ],\n function(results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n email_link: function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n });\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. Its also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n\n__Example__\n\n var iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n ]);\n\n node> var iterator2 = iterator();\n 'one'\n node> var iterator3 = iterator2();\n 'two'\n node> iterator3();\n 'three'\n node> var nextfn = iterator2.next();\n node> nextfn();\n 'three'\n\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n // using apply\n\n async.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n ]);\n\n\n // the same process without using apply\n\n async.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n },\n ]);\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n node> var fn = async.apply(sys.puts, 'one');\n node> fn('two', 'three');\n one\n two\n three\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setTimeout(callback, 0),\nwhich means other higher priority events may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n var call_order = [];\n async.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two]\n });\n call_order.push('one')\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n var slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n };\n var fn = async.memoize(slow_fn);\n\n // fn can now be used as if it were slow_fn\n fn('some name', function () {\n // callback\n });\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n };\n\n node> async.log(hello, 'world');\n 'hello world'\n\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n };\n\n node> async.dir(hello, 'world');\n {hello: 'world'}\n\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", + "_id": "async@0.1.22", + "dist": { + "shasum": "e71b7b78426a1cc4eb66e58c5abd2e5c03c226a2" + }, + "_from": "async@~0.1.22", + "_resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" +} diff --git a/node_modules/grunt/node_modules/coffee-script/.npmignore b/node_modules/grunt/node_modules/coffee-script/.npmignore new file mode 100644 index 000000000..21e430d2e --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/.npmignore @@ -0,0 +1,11 @@ +*.coffee +*.html +.DS_Store +.git* +Cakefile +documentation/ +examples/ +extras/coffee-script.js +raw/ +src/ +test/ diff --git a/node_modules/grunt/node_modules/coffee-script/CNAME b/node_modules/grunt/node_modules/coffee-script/CNAME new file mode 100644 index 000000000..faadabe5f --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/CNAME @@ -0,0 +1 @@ +coffeescript.org \ No newline at end of file diff --git a/node_modules/grunt/node_modules/coffee-script/LICENSE b/node_modules/grunt/node_modules/coffee-script/LICENSE new file mode 100644 index 000000000..dbe6b4e3b --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2012 Jeremy Ashkenas + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt/node_modules/coffee-script/README b/node_modules/grunt/node_modules/coffee-script/README new file mode 100644 index 000000000..69ee6f43c --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/README @@ -0,0 +1,51 @@ + + { + } } { + { { } } + } }{ { + { }{ } } _____ __ __ + ( }{ }{ { ) / ____| / _|/ _| + .- { { } { }} -. | | ___ | |_| |_ ___ ___ + ( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \ + |`-..________ ..-'| | |___| (_) | | | || __/ __/ + | | \_____\___/|_| |_| \___|\___| + | ;--. + | (__ \ _____ _ _ + | | ) ) / ____| (_) | | + | |/ / | (___ ___ _ __ _ _ __ | |_ + | ( / \___ \ / __| '__| | '_ \| __| + | |/ ____) | (__| | | | |_) | |_ + | | |_____/ \___|_| |_| .__/ \__| + `-.._________..-' | | + |_| + + + CoffeeScript is a little language that compiles into JavaScript. + + Install Node.js, and then the CoffeeScript compiler: + sudo bin/cake install + + Or, if you have the Node Package Manager installed: + npm install -g coffee-script + (Leave off the -g if you don't wish to install globally.) + + Execute a script: + coffee /path/to/script.coffee + + Compile a script: + coffee -c /path/to/script.coffee + + For documentation, usage, and examples, see: + http://coffeescript.org/ + + To suggest a feature, report a bug, or general discussion: + http://github.com/jashkenas/coffee-script/issues/ + + If you'd like to chat, drop by #coffeescript on Freenode IRC, + or on webchat.freenode.net. + + The source repository: + git://github.com/jashkenas/coffee-script.git + + All contributors are listed here: + http://github.com/jashkenas/coffee-script/contributors diff --git a/node_modules/grunt/node_modules/coffee-script/Rakefile b/node_modules/grunt/node_modules/coffee-script/Rakefile new file mode 100644 index 000000000..dfb85dabc --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/Rakefile @@ -0,0 +1,78 @@ +require 'rubygems' +require 'erb' +require 'fileutils' +require 'rake/testtask' +require 'json' + +desc "Build the documentation page" +task :doc do + source = 'documentation/index.html.erb' + child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" } + at_exit { Process.kill("INT", child) } + Signal.trap("INT") { exit } + loop do + mtime = File.stat(source).mtime + if !@mtime || mtime > @mtime + rendered = ERB.new(File.read(source)).result(binding) + File.open('index.html', 'w+') {|f| f.write(rendered) } + end + @mtime = mtime + sleep 1 + end +end + +desc "Build coffee-script-source gem" +task :gem do + require 'rubygems' + require 'rubygems/package' + + gemspec = Gem::Specification.new do |s| + s.name = 'coffee-script-source' + s.version = JSON.parse(File.read('package.json'))["version"] + s.date = Time.now.strftime("%Y-%m-%d") + + s.homepage = "http://jashkenas.github.com/coffee-script/" + s.summary = "The CoffeeScript Compiler" + s.description = <<-EOS + CoffeeScript is a little language that compiles into JavaScript. + Underneath all of those embarrassing braces and semicolons, + JavaScript has always had a gorgeous object model at its heart. + CoffeeScript is an attempt to expose the good parts of JavaScript + in a simple way. + EOS + + s.files = [ + 'lib/coffee_script/coffee-script.js', + 'lib/coffee_script/source.rb' + ] + + s.authors = ['Jeremy Ashkenas'] + s.email = 'jashkenas@gmail.com' + s.rubyforge_project = 'coffee-script-source' + end + + file = File.open("coffee-script-source.gem", "w") + Gem::Package.open(file, 'w') do |pkg| + pkg.metadata = gemspec.to_yaml + + path = "lib/coffee_script/source.rb" + contents = <<-ERUBY +module CoffeeScript + module Source + def self.bundled_path + File.expand_path("../coffee-script.js", __FILE__) + end + end +end + ERUBY + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + + contents = File.read("extras/coffee-script.js") + path = "lib/coffee_script/coffee-script.js" + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + end +end diff --git a/node_modules/grunt/node_modules/coffee-script/bin/cake b/node_modules/grunt/node_modules/coffee-script/bin/cake new file mode 100755 index 000000000..5965f4ee5 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/bin/cake @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/cake').run(); diff --git a/node_modules/grunt/node_modules/coffee-script/bin/coffee b/node_modules/grunt/node_modules/coffee-script/bin/coffee new file mode 100755 index 000000000..3d1d71c8c --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/bin/coffee @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/command').run(); diff --git a/node_modules/grunt/node_modules/coffee-script/extras/jsl.conf b/node_modules/grunt/node_modules/coffee-script/extras/jsl.conf new file mode 100644 index 000000000..1190da529 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/extras/jsl.conf @@ -0,0 +1,44 @@ +# JavaScriptLint configuration file for CoffeeScript. + ++no_return_value # function {0} does not always return a value ++duplicate_formal # duplicate formal argument {0} +-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0} ++var_hides_arg # variable {0} hides argument ++redeclared_var # redeclaration of {0} {1} +-anon_no_return_value # anonymous function does not always return a value ++missing_semicolon # missing semicolon ++meaningless_block # meaningless block; curly braces have no impact +-comma_separated_stmts # multiple statements separated by commas (use semicolons?) ++unreachable_code # unreachable code ++missing_break # missing break statement +-missing_break_for_last_case # missing break statement for last case in switch +-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) +-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement +-useless_void # use of the void type may be unnecessary (void is always undefined) ++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs ++use_of_label # use of label +-block_without_braces # block statement without curly braces ++leading_decimal_point # leading decimal point may indicate a number or an object member ++trailing_decimal_point # trailing decimal point may indicate a number or an object member ++octal_number # leading zeros make an octal number ++nested_comment # nested comment ++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma ++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement ++empty_statement # empty statement or extra semicolon +-missing_option_explicit # the "option explicit" control comment is missing ++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag ++dup_option_explicit # duplicate "option explicit" control comment ++useless_assign # useless assignment ++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity ++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent) +-missing_default_case # missing default case in switch statement ++duplicate_case_in_switch # duplicate case in switch statements ++default_not_at_end # the default case is not at the end of the switch statement ++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax ++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax ++useless_comparison # useless comparison; comparing identical expressions ++with_statement # with statement hides undeclared variables; use temporary variable instead ++trailing_comma_in_array # extra comma is not recommended in array initializers ++assign_to_function_call # assignment to a function call ++parseint_missing_radix # parseInt missing radix parameter ++lambda_assign_requires_semicolon diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/browser.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/browser.js new file mode 100644 index 000000000..825cbf312 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/browser.js @@ -0,0 +1,92 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var CoffeeScript, runScripts; + + CoffeeScript = require('./coffee-script'); + + CoffeeScript.require = require; + + CoffeeScript["eval"] = function(code, options) { + var _ref; + if (options == null) { + options = {}; + } + if ((_ref = options.bare) == null) { + options.bare = true; + } + return eval(CoffeeScript.compile(code, options)); + }; + + CoffeeScript.run = function(code, options) { + if (options == null) { + options = {}; + } + options.bare = true; + return Function(CoffeeScript.compile(code, options))(); + }; + + if (typeof window === "undefined" || window === null) { + return; + } + + CoffeeScript.load = function(url, callback) { + var xhr; + xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP'); + xhr.open('GET', url, true); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + var _ref; + if (xhr.readyState === 4) { + if ((_ref = xhr.status) === 0 || _ref === 200) { + CoffeeScript.run(xhr.responseText); + } else { + throw new Error("Could not load " + url); + } + if (callback) { + return callback(); + } + } + }; + return xhr.send(null); + }; + + runScripts = function() { + var coffees, execute, index, length, s, scripts; + scripts = document.getElementsByTagName('script'); + coffees = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = scripts.length; _i < _len; _i++) { + s = scripts[_i]; + if (s.type === 'text/coffeescript') { + _results.push(s); + } + } + return _results; + })(); + index = 0; + length = coffees.length; + (execute = function() { + var script; + script = coffees[index++]; + if ((script != null ? script.type : void 0) === 'text/coffeescript') { + if (script.src) { + return CoffeeScript.load(script.src, execute); + } else { + CoffeeScript.run(script.innerHTML); + return execute(); + } + } + })(); + return null; + }; + + if (window.addEventListener) { + addEventListener('DOMContentLoaded', runScripts, false); + } else { + attachEvent('onload', runScripts); + } + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/cake.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/cake.js new file mode 100644 index 000000000..1523418f1 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/cake.js @@ -0,0 +1,111 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + tasks = {}; + + options = {}; + + switches = []; + + oparse = null; + + helpers.extend(global, { + task: function(name, description, action) { + var _ref; + if (!action) { + _ref = [description, action], action = _ref[0], description = _ref[1]; + } + return tasks[name] = { + name: name, + description: description, + action: action + }; + }, + option: function(letter, flag, description) { + return switches.push([letter, flag, description]); + }, + invoke: function(name) { + if (!tasks[name]) { + missingTask(name); + } + return tasks[name].action(options); + } + }); + + exports.run = function() { + var arg, args, _i, _len, _ref, _results; + global.__originalDirname = fs.realpathSync('.'); + process.chdir(cakefileDirectory(__originalDirname)); + args = process.argv.slice(2); + CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { + filename: 'Cakefile' + }); + oparse = new optparse.OptionParser(switches); + if (!args.length) { + return printTasks(); + } + try { + options = oparse.parse(args); + } catch (e) { + return fatalError("" + e); + } + _ref = options["arguments"]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + arg = _ref[_i]; + _results.push(invoke(arg)); + } + return _results; + }; + + printTasks = function() { + var cakefilePath, desc, name, relative, spaces, task; + relative = path.relative || path.resolve; + cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile'); + console.log("" + cakefilePath + " defines the following tasks:\n"); + for (name in tasks) { + task = tasks[name]; + spaces = 20 - name.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + desc = task.description ? "# " + task.description : ''; + console.log("cake " + name + spaces + " " + desc); + } + if (switches.length) { + return console.log(oparse.help()); + } + }; + + fatalError = function(message) { + console.error(message + '\n'); + console.log('To see a list of all tasks/options, run "cake"'); + return process.exit(1); + }; + + missingTask = function(task) { + return fatalError("No such task: " + task); + }; + + cakefileDirectory = function(dir) { + var parent; + if (path.existsSync(path.join(dir, 'Cakefile'))) { + return dir; + } + parent = path.normalize(path.join(dir, '..')); + if (parent !== dir) { + return cakefileDirectory(parent); + } + throw new Error("Cakefile not found in " + (process.cwd())); + }; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/coffee-script.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/coffee-script.js new file mode 100644 index 000000000..c43fa497e --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/coffee-script.js @@ -0,0 +1,167 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref, + __hasProp = {}.hasOwnProperty; + + fs = require('fs'); + + path = require('path'); + + _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED; + + parser = require('./parser').parser; + + vm = require('vm'); + + if (require.extensions) { + require.extensions['.coffee'] = function(module, filename) { + var content; + content = compile(fs.readFileSync(filename, 'utf8'), { + filename: filename + }); + return module._compile(content, filename); + }; + } else if (require.registerExtension) { + require.registerExtension('.coffee', function(content) { + return compile(content); + }); + } + + exports.VERSION = '1.3.3'; + + exports.RESERVED = RESERVED; + + exports.helpers = require('./helpers'); + + exports.compile = compile = function(code, options) { + var header, js, merge; + if (options == null) { + options = {}; + } + merge = exports.helpers.merge; + try { + js = (parser.parse(lexer.tokenize(code))).compile(options); + if (!options.header) { + return js; + } + } catch (err) { + if (options.filename) { + err.message = "In " + options.filename + ", " + err.message; + } + throw err; + } + header = "Generated by CoffeeScript " + this.VERSION; + return "// " + header + "\n" + js; + }; + + exports.tokens = function(code, options) { + return lexer.tokenize(code, options); + }; + + exports.nodes = function(source, options) { + if (typeof source === 'string') { + return parser.parse(lexer.tokenize(source, options)); + } else { + return parser.parse(source); + } + }; + + exports.run = function(code, options) { + var mainModule; + if (options == null) { + options = {}; + } + mainModule = require.main; + mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.'; + mainModule.moduleCache && (mainModule.moduleCache = {}); + mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename))); + if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) { + return mainModule._compile(compile(code, options), mainModule.filename); + } else { + return mainModule._compile(code, mainModule.filename); + } + }; + + exports["eval"] = function(code, options) { + var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref1, _ref2, _require; + if (options == null) { + options = {}; + } + if (!(code = code.trim())) { + return; + } + Script = vm.Script; + if (Script) { + if (options.sandbox != null) { + if (options.sandbox instanceof Script.createContext().constructor) { + sandbox = options.sandbox; + } else { + sandbox = Script.createContext(); + _ref1 = options.sandbox; + for (k in _ref1) { + if (!__hasProp.call(_ref1, k)) continue; + v = _ref1[k]; + sandbox[k] = v; + } + } + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; + } else { + sandbox = global; + } + sandbox.__filename = options.filename || 'eval'; + sandbox.__dirname = path.dirname(sandbox.__filename); + if (!(sandbox !== global || sandbox.module || sandbox.require)) { + Module = require('module'); + sandbox.module = _module = new Module(options.modulename || 'eval'); + sandbox.require = _require = function(path) { + return Module._load(path, _module, true); + }; + _module.filename = sandbox.__filename; + _ref2 = Object.getOwnPropertyNames(require); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + r = _ref2[_i]; + if (r !== 'paths') { + _require[r] = require[r]; + } + } + _require.paths = _module.paths = Module._nodeModulePaths(process.cwd()); + _require.resolve = function(request) { + return Module._resolveFilename(request, _module); + }; + } + } + o = {}; + for (k in options) { + if (!__hasProp.call(options, k)) continue; + v = options[k]; + o[k] = v; + } + o.bare = true; + js = compile(code, o); + if (sandbox === global) { + return vm.runInThisContext(js); + } else { + return vm.runInContext(js, sandbox); + } + }; + + lexer = new Lexer; + + parser.lexer = { + lex: function() { + var tag, _ref1; + _ref1 = this.tokens[this.pos++] || [''], tag = _ref1[0], this.yytext = _ref1[1], this.yylineno = _ref1[2]; + return tag; + }, + setInput: function(tokens) { + this.tokens = tokens; + return this.pos = 0; + }, + upcomingInput: function() { + return ""; + } + }; + + parser.yy = require('./nodes'); + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/command.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/command.js new file mode 100644 index 000000000..e02da9fe6 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/command.js @@ -0,0 +1,500 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, hidden, joinTimeout, lint, loadRequires, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec; + + EventEmitter = require('events').EventEmitter; + + helpers.extend(CoffeeScript, new EventEmitter); + + printLine = function(line) { + return process.stdout.write(line + '\n'); + }; + + printWarn = function(line) { + return process.stderr.write(line + '\n'); + }; + + hidden = function(file) { + return /^\.|~$/.test(file); + }; + + BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.'; + + SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; + + opts = {}; + + sources = []; + + sourceCode = []; + + notSources = {}; + + watchers = {}; + + optionParser = null; + + exports.run = function() { + var literals, source, _i, _len, _results; + parseOptions(); + if (opts.nodejs) { + return forkNode(); + } + if (opts.help) { + return usage(); + } + if (opts.version) { + return version(); + } + if (opts.require) { + loadRequires(); + } + if (opts.interactive) { + return require('./repl'); + } + if (opts.watch && !fs.watch) { + return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + "."); + } + if (opts.stdio) { + return compileStdio(); + } + if (opts["eval"]) { + return compileScript(null, sources[0]); + } + if (!sources.length) { + return require('./repl'); + } + literals = opts.run ? sources.splice(1) : []; + process.argv = process.argv.slice(0, 2).concat(literals); + process.argv[0] = 'coffee'; + process.execPath = require.main.filename; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + source = sources[_i]; + _results.push(compilePath(source, true, path.normalize(source))); + } + return _results; + }; + + compilePath = function(source, topLevel, base) { + return fs.stat(source, function(err, stats) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + if (topLevel && source.slice(-7) !== '.coffee') { + source = sources[sources.indexOf(source)] = "" + source + ".coffee"; + return compilePath(source, topLevel, base); + } + if (topLevel) { + console.error("File not found: " + source); + process.exit(1); + } + return; + } + if (stats.isDirectory()) { + if (opts.watch) { + watchDir(source, base); + } + return fs.readdir(source, function(err, files) { + var file, index, _ref1, _ref2; + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + index = sources.indexOf(source); + files = files.filter(function(file) { + return !hidden(file); + }); + [].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(path.join(source, file)); + } + return _results; + })())), _ref1; + [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() { + return null; + }))), _ref2; + return files.forEach(function(file) { + return compilePath(path.join(source, file), false, base); + }); + }); + } else if (topLevel || path.extname(source) === '.coffee') { + if (opts.watch) { + watch(source, base); + } + return fs.readFile(source, function(err, code) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + return compileScript(source, code.toString(), base); + }); + } else { + notSources[source] = true; + return removeSource(source, base); + } + }); + }; + + compileScript = function(file, input, base) { + var o, options, t, task; + o = opts; + options = compileOptions(file); + try { + t = task = { + file: file, + input: input, + options: options + }; + CoffeeScript.emit('compile', task); + if (o.tokens) { + return printTokens(CoffeeScript.tokens(t.input)); + } else if (o.nodes) { + return printLine(CoffeeScript.nodes(t.input).toString().trim()); + } else if (o.run) { + return CoffeeScript.run(t.input, t.options); + } else if (o.join && t.file !== o.join) { + sourceCode[sources.indexOf(t.file)] = t.input; + return compileJoin(); + } else { + t.output = CoffeeScript.compile(t.input, t.options); + CoffeeScript.emit('success', task); + if (o.print) { + return printLine(t.output.trim()); + } else if (o.compile) { + return writeJs(t.file, t.output, base); + } else if (o.lint) { + return lint(t.file, t.output); + } + } + } catch (err) { + CoffeeScript.emit('failure', err, task); + if (CoffeeScript.listeners('failure').length) { + return; + } + if (o.watch) { + return printLine(err.message + '\x07'); + } + printWarn(err instanceof Error && err.stack || ("ERROR: " + err)); + return process.exit(1); + } + }; + + compileStdio = function() { + var code, stdin; + code = ''; + stdin = process.openStdin(); + stdin.on('data', function(buffer) { + if (buffer) { + return code += buffer.toString(); + } + }); + return stdin.on('end', function() { + return compileScript(null, code); + }); + }; + + joinTimeout = null; + + compileJoin = function() { + if (!opts.join) { + return; + } + if (!sourceCode.some(function(code) { + return code === null; + })) { + clearTimeout(joinTimeout); + return joinTimeout = wait(100, function() { + return compileScript(opts.join, sourceCode.join('\n'), opts.join); + }); + } + }; + + loadRequires = function() { + var realFilename, req, _i, _len, _ref1; + realFilename = module.filename; + module.filename = '.'; + _ref1 = opts.require; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + req = _ref1[_i]; + require(req); + } + return module.filename = realFilename; + }; + + watch = function(source, base) { + var compile, compileTimeout, prevStats, rewatch, watchErr, watcher; + prevStats = null; + compileTimeout = null; + watchErr = function(e) { + if (e.code === 'ENOENT') { + if (sources.indexOf(source) === -1) { + return; + } + try { + rewatch(); + return compile(); + } catch (e) { + removeSource(source, base, true); + return compileJoin(); + } + } else { + throw e; + } + }; + compile = function() { + clearTimeout(compileTimeout); + return compileTimeout = wait(25, function() { + return fs.stat(source, function(err, stats) { + if (err) { + return watchErr(err); + } + if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) { + return rewatch(); + } + prevStats = stats; + return fs.readFile(source, function(err, code) { + if (err) { + return watchErr(err); + } + compileScript(source, code.toString(), base); + return rewatch(); + }); + }); + }); + }; + try { + watcher = fs.watch(source, compile); + } catch (e) { + watchErr(e); + } + return rewatch = function() { + if (watcher != null) { + watcher.close(); + } + return watcher = fs.watch(source, compile); + }; + }; + + watchDir = function(source, base) { + var readdirTimeout, watcher; + readdirTimeout = null; + try { + return watcher = fs.watch(source, function() { + clearTimeout(readdirTimeout); + return readdirTimeout = wait(25, function() { + return fs.readdir(source, function(err, files) { + var file, _i, _len, _results; + if (err) { + if (err.code !== 'ENOENT') { + throw err; + } + watcher.close(); + return unwatchDir(source, base); + } + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + if (!(!hidden(file) && !notSources[file])) { + continue; + } + file = path.join(source, file); + if (sources.some(function(s) { + return s.indexOf(file) >= 0; + })) { + continue; + } + sources.push(file); + sourceCode.push(null); + _results.push(compilePath(file, false, base)); + } + return _results; + }); + }); + }); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; + } + } + }; + + unwatchDir = function(source, base) { + var file, prevSources, toRemove, _i, _len; + prevSources = sources.slice(0); + toRemove = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + file = sources[_i]; + if (file.indexOf(source) >= 0) { + _results.push(file); + } + } + return _results; + })(); + for (_i = 0, _len = toRemove.length; _i < _len; _i++) { + file = toRemove[_i]; + removeSource(file, base, true); + } + if (!sources.some(function(s, i) { + return prevSources[i] !== s; + })) { + return; + } + return compileJoin(); + }; + + removeSource = function(source, base, removeJs) { + var index, jsPath; + index = sources.indexOf(source); + sources.splice(index, 1); + sourceCode.splice(index, 1); + if (removeJs && !opts.join) { + jsPath = outputPath(source, base); + return path.exists(jsPath, function(exists) { + if (exists) { + return fs.unlink(jsPath, function(err) { + if (err && err.code !== 'ENOENT') { + throw err; + } + return timeLog("removed " + source); + }); + } + }); + } + }; + + outputPath = function(source, base) { + var baseDir, dir, filename, srcDir; + filename = path.basename(source, path.extname(source)) + '.js'; + srcDir = path.dirname(source); + baseDir = base === '.' ? srcDir : srcDir.substring(base.length); + dir = opts.output ? path.join(opts.output, baseDir) : srcDir; + return path.join(dir, filename); + }; + + writeJs = function(source, js, base) { + var compile, jsDir, jsPath; + jsPath = outputPath(source, base); + jsDir = path.dirname(jsPath); + compile = function() { + if (js.length <= 0) { + js = ' '; + } + return fs.writeFile(jsPath, js, function(err) { + if (err) { + return printLine(err.message); + } else if (opts.compile && opts.watch) { + return timeLog("compiled " + source); + } + }); + }; + return path.exists(jsDir, function(exists) { + if (exists) { + return compile(); + } else { + return exec("mkdir -p " + jsDir, compile); + } + }); + }; + + wait = function(milliseconds, func) { + return setTimeout(func, milliseconds); + }; + + timeLog = function(message) { + return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message); + }; + + lint = function(file, js) { + var conf, jsl, printIt; + printIt = function(buffer) { + return printLine(file + ':\t' + buffer.toString().trim()); + }; + conf = __dirname + '/../../extras/jsl.conf'; + jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]); + jsl.stdout.on('data', printIt); + jsl.stderr.on('data', printIt); + jsl.stdin.write(js); + return jsl.stdin.end(); + }; + + printTokens = function(tokens) { + var strings, tag, token, value; + strings = (function() { + var _i, _len, _ref1, _results; + _results = []; + for (_i = 0, _len = tokens.length; _i < _len; _i++) { + token = tokens[_i]; + _ref1 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref1[0], value = _ref1[1]; + _results.push("[" + tag + " " + value + "]"); + } + return _results; + })(); + return printLine(strings.join(' ')); + }; + + parseOptions = function() { + var i, o, source, _i, _len; + optionParser = new optparse.OptionParser(SWITCHES, BANNER); + o = opts = optionParser.parse(process.argv.slice(2)); + o.compile || (o.compile = !!o.output); + o.run = !(o.compile || o.print || o.lint); + o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)); + sources = o["arguments"]; + for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { + source = sources[i]; + sourceCode[i] = null; + } + }; + + compileOptions = function(filename) { + return { + filename: filename, + bare: opts.bare, + header: opts.compile + }; + }; + + forkNode = function() { + var args, nodeArgs; + nodeArgs = opts.nodejs.split(/\s+/); + args = process.argv.slice(1); + args.splice(args.indexOf('--nodejs'), 2); + return spawn(process.execPath, nodeArgs.concat(args), { + cwd: process.cwd(), + env: process.env, + customFds: [0, 1, 2] + }); + }; + + usage = function() { + return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help()); + }; + + version = function() { + return printLine("CoffeeScript version " + CoffeeScript.VERSION); + }; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/grammar.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/grammar.js new file mode 100644 index 000000000..56621388d --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/grammar.js @@ -0,0 +1,606 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap; + + Parser = require('jison').Parser; + + unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/; + + o = function(patternString, action, options) { + var match; + patternString = patternString.replace(/\s{2,}/g, ' '); + if (!action) { + return [patternString, '$$ = $1;', options]; + } + action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())"; + action = action.replace(/\bnew /g, '$&yy.'); + action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&'); + return [patternString, "$$ = " + action + ";", options]; + }; + + grammar = { + Root: [ + o('', function() { + return new Block; + }), o('Body'), o('Block TERMINATOR') + ], + Body: [ + o('Line', function() { + return Block.wrap([$1]); + }), o('Body TERMINATOR Line', function() { + return $1.push($3); + }), o('Body TERMINATOR') + ], + Line: [o('Expression'), o('Statement')], + Statement: [ + o('Return'), o('Comment'), o('STATEMENT', function() { + return new Literal($1); + }) + ], + Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')], + Block: [ + o('INDENT OUTDENT', function() { + return new Block; + }), o('INDENT Body OUTDENT', function() { + return $2; + }) + ], + Identifier: [ + o('IDENTIFIER', function() { + return new Literal($1); + }) + ], + AlphaNumeric: [ + o('NUMBER', function() { + return new Literal($1); + }), o('STRING', function() { + return new Literal($1); + }) + ], + Literal: [ + o('AlphaNumeric'), o('JS', function() { + return new Literal($1); + }), o('REGEX', function() { + return new Literal($1); + }), o('DEBUGGER', function() { + return new Literal($1); + }), o('UNDEFINED', function() { + return new Undefined; + }), o('NULL', function() { + return new Null; + }), o('BOOL', function() { + return new Bool($1); + }) + ], + Assign: [ + o('Assignable = Expression', function() { + return new Assign($1, $3); + }), o('Assignable = TERMINATOR Expression', function() { + return new Assign($1, $4); + }), o('Assignable = INDENT Expression OUTDENT', function() { + return new Assign($1, $4); + }) + ], + AssignObj: [ + o('ObjAssignable', function() { + return new Value($1); + }), o('ObjAssignable : Expression', function() { + return new Assign(new Value($1), $3, 'object'); + }), o('ObjAssignable :\ + INDENT Expression OUTDENT', function() { + return new Assign(new Value($1), $4, 'object'); + }), o('Comment') + ], + ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')], + Return: [ + o('RETURN Expression', function() { + return new Return($2); + }), o('RETURN', function() { + return new Return; + }) + ], + Comment: [ + o('HERECOMMENT', function() { + return new Comment($1); + }) + ], + Code: [ + o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() { + return new Code($2, $5, $4); + }), o('FuncGlyph Block', function() { + return new Code([], $2, $1); + }) + ], + FuncGlyph: [ + o('->', function() { + return 'func'; + }), o('=>', function() { + return 'boundfunc'; + }) + ], + OptComma: [o(''), o(',')], + ParamList: [ + o('', function() { + return []; + }), o('Param', function() { + return [$1]; + }), o('ParamList , Param', function() { + return $1.concat($3); + }), o('ParamList OptComma TERMINATOR Param', function() { + return $1.concat($4); + }), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Param: [ + o('ParamVar', function() { + return new Param($1); + }), o('ParamVar ...', function() { + return new Param($1, null, true); + }), o('ParamVar = Expression', function() { + return new Param($1, $3); + }) + ], + ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')], + Splat: [ + o('Expression ...', function() { + return new Splat($1); + }) + ], + SimpleAssignable: [ + o('Identifier', function() { + return new Value($1); + }), o('Value Accessor', function() { + return $1.add($2); + }), o('Invocation Accessor', function() { + return new Value($1, [].concat($2)); + }), o('ThisProperty') + ], + Assignable: [ + o('SimpleAssignable'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + Value: [ + o('Assignable'), o('Literal', function() { + return new Value($1); + }), o('Parenthetical', function() { + return new Value($1); + }), o('Range', function() { + return new Value($1); + }), o('This') + ], + Accessor: [ + o('. Identifier', function() { + return new Access($2); + }), o('?. Identifier', function() { + return new Access($2, 'soak'); + }), o(':: Identifier', function() { + return [new Access(new Literal('prototype')), new Access($2)]; + }), o('::', function() { + return new Access(new Literal('prototype')); + }), o('Index') + ], + Index: [ + o('INDEX_START IndexValue INDEX_END', function() { + return $2; + }), o('INDEX_SOAK Index', function() { + return extend($2, { + soak: true + }); + }) + ], + IndexValue: [ + o('Expression', function() { + return new Index($1); + }), o('Slice', function() { + return new Slice($1); + }) + ], + Object: [ + o('{ AssignList OptComma }', function() { + return new Obj($2, $1.generated); + }) + ], + AssignList: [ + o('', function() { + return []; + }), o('AssignObj', function() { + return [$1]; + }), o('AssignList , AssignObj', function() { + return $1.concat($3); + }), o('AssignList OptComma TERMINATOR AssignObj', function() { + return $1.concat($4); + }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Class: [ + o('CLASS', function() { + return new Class; + }), o('CLASS Block', function() { + return new Class(null, null, $2); + }), o('CLASS EXTENDS Expression', function() { + return new Class(null, $3); + }), o('CLASS EXTENDS Expression Block', function() { + return new Class(null, $3, $4); + }), o('CLASS SimpleAssignable', function() { + return new Class($2); + }), o('CLASS SimpleAssignable Block', function() { + return new Class($2, null, $3); + }), o('CLASS SimpleAssignable EXTENDS Expression', function() { + return new Class($2, $4); + }), o('CLASS SimpleAssignable EXTENDS Expression Block', function() { + return new Class($2, $4, $5); + }) + ], + Invocation: [ + o('Value OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('Invocation OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('SUPER', function() { + return new Call('super', [new Splat(new Literal('arguments'))]); + }), o('SUPER Arguments', function() { + return new Call('super', $2); + }) + ], + OptFuncExist: [ + o('', function() { + return false; + }), o('FUNC_EXIST', function() { + return true; + }) + ], + Arguments: [ + o('CALL_START CALL_END', function() { + return []; + }), o('CALL_START ArgList OptComma CALL_END', function() { + return $2; + }) + ], + This: [ + o('THIS', function() { + return new Value(new Literal('this')); + }), o('@', function() { + return new Value(new Literal('this')); + }) + ], + ThisProperty: [ + o('@ Identifier', function() { + return new Value(new Literal('this'), [new Access($2)], 'this'); + }) + ], + Array: [ + o('[ ]', function() { + return new Arr([]); + }), o('[ ArgList OptComma ]', function() { + return new Arr($2); + }) + ], + RangeDots: [ + o('..', function() { + return 'inclusive'; + }), o('...', function() { + return 'exclusive'; + }) + ], + Range: [ + o('[ Expression RangeDots Expression ]', function() { + return new Range($2, $4, $3); + }) + ], + Slice: [ + o('Expression RangeDots Expression', function() { + return new Range($1, $3, $2); + }), o('Expression RangeDots', function() { + return new Range($1, null, $2); + }), o('RangeDots Expression', function() { + return new Range(null, $2, $1); + }), o('RangeDots', function() { + return new Range(null, null, $1); + }) + ], + ArgList: [ + o('Arg', function() { + return [$1]; + }), o('ArgList , Arg', function() { + return $1.concat($3); + }), o('ArgList OptComma TERMINATOR Arg', function() { + return $1.concat($4); + }), o('INDENT ArgList OptComma OUTDENT', function() { + return $2; + }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Arg: [o('Expression'), o('Splat')], + SimpleArgs: [ + o('Expression'), o('SimpleArgs , Expression', function() { + return [].concat($1, $3); + }) + ], + Try: [ + o('TRY Block', function() { + return new Try($2); + }), o('TRY Block Catch', function() { + return new Try($2, $3[0], $3[1]); + }), o('TRY Block FINALLY Block', function() { + return new Try($2, null, null, $4); + }), o('TRY Block Catch FINALLY Block', function() { + return new Try($2, $3[0], $3[1], $5); + }) + ], + Catch: [ + o('CATCH Identifier Block', function() { + return [$2, $3]; + }) + ], + Throw: [ + o('THROW Expression', function() { + return new Throw($2); + }) + ], + Parenthetical: [ + o('( Body )', function() { + return new Parens($2); + }), o('( INDENT Body OUTDENT )', function() { + return new Parens($3); + }) + ], + WhileSource: [ + o('WHILE Expression', function() { + return new While($2); + }), o('WHILE Expression WHEN Expression', function() { + return new While($2, { + guard: $4 + }); + }), o('UNTIL Expression', function() { + return new While($2, { + invert: true + }); + }), o('UNTIL Expression WHEN Expression', function() { + return new While($2, { + invert: true, + guard: $4 + }); + }) + ], + While: [ + o('WhileSource Block', function() { + return $1.addBody($2); + }), o('Statement WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Expression WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Loop', function() { + return $1; + }) + ], + Loop: [ + o('LOOP Block', function() { + return new While(new Literal('true')).addBody($2); + }), o('LOOP Expression', function() { + return new While(new Literal('true')).addBody(Block.wrap([$2])); + }) + ], + For: [ + o('Statement ForBody', function() { + return new For($1, $2); + }), o('Expression ForBody', function() { + return new For($1, $2); + }), o('ForBody Block', function() { + return new For($2, $1); + }) + ], + ForBody: [ + o('FOR Range', function() { + return { + source: new Value($2) + }; + }), o('ForStart ForSource', function() { + $2.own = $1.own; + $2.name = $1[0]; + $2.index = $1[1]; + return $2; + }) + ], + ForStart: [ + o('FOR ForVariables', function() { + return $2; + }), o('FOR OWN ForVariables', function() { + $3.own = true; + return $3; + }) + ], + ForValue: [ + o('Identifier'), o('ThisProperty'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + ForVariables: [ + o('ForValue', function() { + return [$1]; + }), o('ForValue , ForValue', function() { + return [$1, $3]; + }) + ], + ForSource: [ + o('FORIN Expression', function() { + return { + source: $2 + }; + }), o('FOROF Expression', function() { + return { + source: $2, + object: true + }; + }), o('FORIN Expression WHEN Expression', function() { + return { + source: $2, + guard: $4 + }; + }), o('FOROF Expression WHEN Expression', function() { + return { + source: $2, + guard: $4, + object: true + }; + }), o('FORIN Expression BY Expression', function() { + return { + source: $2, + step: $4 + }; + }), o('FORIN Expression WHEN Expression BY Expression', function() { + return { + source: $2, + guard: $4, + step: $6 + }; + }), o('FORIN Expression BY Expression WHEN Expression', function() { + return { + source: $2, + step: $4, + guard: $6 + }; + }) + ], + Switch: [ + o('SWITCH Expression INDENT Whens OUTDENT', function() { + return new Switch($2, $4); + }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() { + return new Switch($2, $4, $6); + }), o('SWITCH INDENT Whens OUTDENT', function() { + return new Switch(null, $3); + }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() { + return new Switch(null, $3, $5); + }) + ], + Whens: [ + o('When'), o('Whens When', function() { + return $1.concat($2); + }) + ], + When: [ + o('LEADING_WHEN SimpleArgs Block', function() { + return [[$2, $3]]; + }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() { + return [[$2, $3]]; + }) + ], + IfBlock: [ + o('IF Expression Block', function() { + return new If($2, $3, { + type: $1 + }); + }), o('IfBlock ELSE IF Expression Block', function() { + return $1.addElse(new If($4, $5, { + type: $3 + })); + }) + ], + If: [ + o('IfBlock'), o('IfBlock ELSE Block', function() { + return $1.addElse($3); + }), o('Statement POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }), o('Expression POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }) + ], + Operation: [ + o('UNARY Expression', function() { + return new Op($1, $2); + }), o('- Expression', (function() { + return new Op('-', $2); + }), { + prec: 'UNARY' + }), o('+ Expression', (function() { + return new Op('+', $2); + }), { + prec: 'UNARY' + }), o('-- SimpleAssignable', function() { + return new Op('--', $2); + }), o('++ SimpleAssignable', function() { + return new Op('++', $2); + }), o('SimpleAssignable --', function() { + return new Op('--', $1, null, true); + }), o('SimpleAssignable ++', function() { + return new Op('++', $1, null, true); + }), o('Expression ?', function() { + return new Existence($1); + }), o('Expression + Expression', function() { + return new Op('+', $1, $3); + }), o('Expression - Expression', function() { + return new Op('-', $1, $3); + }), o('Expression MATH Expression', function() { + return new Op($2, $1, $3); + }), o('Expression SHIFT Expression', function() { + return new Op($2, $1, $3); + }), o('Expression COMPARE Expression', function() { + return new Op($2, $1, $3); + }), o('Expression LOGIC Expression', function() { + return new Op($2, $1, $3); + }), o('Expression RELATION Expression', function() { + if ($2.charAt(0) === '!') { + return new Op($2.slice(1), $1, $3).invert(); + } else { + return new Op($2, $1, $3); + } + }), o('SimpleAssignable COMPOUND_ASSIGN\ + Expression', function() { + return new Assign($1, $3, $2); + }), o('SimpleAssignable COMPOUND_ASSIGN\ + INDENT Expression OUTDENT', function() { + return new Assign($1, $4, $2); + }), o('SimpleAssignable EXTENDS Expression', function() { + return new Extends($1, $3); + }) + ] + }; + + operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']]; + + tokens = []; + + for (name in grammar) { + alternatives = grammar[name]; + grammar[name] = (function() { + var _i, _j, _len, _len1, _ref, _results; + _results = []; + for (_i = 0, _len = alternatives.length; _i < _len; _i++) { + alt = alternatives[_i]; + _ref = alt[0].split(' '); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + token = _ref[_j]; + if (!grammar[token]) { + tokens.push(token); + } + } + if (name === 'Root') { + alt[1] = "return " + alt[1]; + } + _results.push(alt); + } + return _results; + })(); + } + + exports.parser = new Parser({ + tokens: tokens.join(' '), + bnf: grammar, + operators: operators.reverse(), + startSymbol: 'Root' + }); + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/helpers.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/helpers.js new file mode 100644 index 000000000..b0a997b8d --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/helpers.js @@ -0,0 +1,77 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var extend, flatten; + + exports.starts = function(string, literal, start) { + return literal === string.substr(start, literal.length); + }; + + exports.ends = function(string, literal, back) { + var len; + len = literal.length; + return literal === string.substr(string.length - len - (back || 0), len); + }; + + exports.compact = function(array) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + item = array[_i]; + if (item) { + _results.push(item); + } + } + return _results; + }; + + exports.count = function(string, substr) { + var num, pos; + num = pos = 0; + if (!substr.length) { + return 1 / 0; + } + while (pos = 1 + string.indexOf(substr, pos)) { + num++; + } + return num; + }; + + exports.merge = function(options, overrides) { + return extend(extend({}, options), overrides); + }; + + extend = exports.extend = function(object, properties) { + var key, val; + for (key in properties) { + val = properties[key]; + object[key] = val; + } + return object; + }; + + exports.flatten = flatten = function(array) { + var element, flattened, _i, _len; + flattened = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + element = array[_i]; + if (element instanceof Array) { + flattened = flattened.concat(flatten(element)); + } else { + flattened.push(element); + } + } + return flattened; + }; + + exports.del = function(obj, key) { + var val; + val = obj[key]; + delete obj[key]; + return val; + }; + + exports.last = function(array, back) { + return array[array.length - (back || 0) - 1]; + }; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/index.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/index.js new file mode 100644 index 000000000..d344c41a2 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/index.js @@ -0,0 +1,11 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var key, val, _ref; + + _ref = require('./coffee-script'); + for (key in _ref) { + val = _ref[key]; + exports[key] = val; + } + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/lexer.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/lexer.js new file mode 100644 index 000000000..f80a44337 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/lexer.js @@ -0,0 +1,788 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES; + + _ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last; + + exports.Lexer = Lexer = (function() { + + function Lexer() {} + + Lexer.prototype.tokenize = function(code, opts) { + var i, tag; + if (opts == null) { + opts = {}; + } + if (WHITESPACE.test(code)) { + code = "\n" + code; + } + code = code.replace(/\r/g, '').replace(TRAILING_SPACES, ''); + this.code = code; + this.line = opts.line || 0; + this.indent = 0; + this.indebt = 0; + this.outdebt = 0; + this.indents = []; + this.ends = []; + this.tokens = []; + i = 0; + while (this.chunk = code.slice(i)) { + i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken(); + } + this.closeIndentation(); + if (tag = this.ends.pop()) { + this.error("missing " + tag); + } + if (opts.rewrite === false) { + return this.tokens; + } + return (new Rewriter).rewrite(this.tokens); + }; + + Lexer.prototype.identifierToken = function() { + var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3; + if (!(match = IDENTIFIER.exec(this.chunk))) { + return 0; + } + input = match[0], id = match[1], colon = match[2]; + if (id === 'own' && this.tag() === 'FOR') { + this.token('OWN', id); + return id.length; + } + forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@'); + tag = 'IDENTIFIER'; + if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) { + tag = id.toUpperCase(); + if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) { + tag = 'LEADING_WHEN'; + } else if (tag === 'FOR') { + this.seenFor = true; + } else if (tag === 'UNLESS') { + tag = 'IF'; + } else if (__indexOf.call(UNARY, tag) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(RELATION, tag) >= 0) { + if (tag !== 'INSTANCEOF' && this.seenFor) { + tag = 'FOR' + tag; + this.seenFor = false; + } else { + tag = 'RELATION'; + if (this.value() === '!') { + this.tokens.pop(); + id = '!' + id; + } + } + } + } + if (__indexOf.call(JS_FORBIDDEN, id) >= 0) { + if (forcedIdentifier) { + tag = 'IDENTIFIER'; + id = new String(id); + id.reserved = true; + } else if (__indexOf.call(RESERVED, id) >= 0) { + this.error("reserved word \"" + id + "\""); + } + } + if (!forcedIdentifier) { + if (__indexOf.call(COFFEE_ALIASES, id) >= 0) { + id = COFFEE_ALIAS_MAP[id]; + } + tag = (function() { + switch (id) { + case '!': + return 'UNARY'; + case '==': + case '!=': + return 'COMPARE'; + case '&&': + case '||': + return 'LOGIC'; + case 'true': + case 'false': + return 'BOOL'; + case 'break': + case 'continue': + return 'STATEMENT'; + default: + return tag; + } + })(); + } + this.token(tag, id); + if (colon) { + this.token(':', ':'); + } + return input.length; + }; + + Lexer.prototype.numberToken = function() { + var binaryLiteral, lexedLength, match, number, octalLiteral; + if (!(match = NUMBER.exec(this.chunk))) { + return 0; + } + number = match[0]; + if (/^0[BOX]/.test(number)) { + this.error("radix prefix '" + number + "' must be lowercase"); + } else if (/E/.test(number) && !/^0x/.test(number)) { + this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'"); + } else if (/^0\d*[89]/.test(number)) { + this.error("decimal literal '" + number + "' must not be prefixed with '0'"); + } else if (/^0\d+/.test(number)) { + this.error("octal literal '" + number + "' must be prefixed with '0o'"); + } + lexedLength = number.length; + if (octalLiteral = /^0o([0-7]+)/.exec(number)) { + number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16); + } + if (binaryLiteral = /^0b([01]+)/.exec(number)) { + number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16); + } + this.token('NUMBER', number); + return lexedLength; + }; + + Lexer.prototype.stringToken = function() { + var match, octalEsc, string; + switch (this.chunk.charAt(0)) { + case "'": + if (!(match = SIMPLESTR.exec(this.chunk))) { + return 0; + } + this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n')); + break; + case '"': + if (!(string = this.balancedString(this.chunk, '"'))) { + return 0; + } + if (0 < string.indexOf('#{', 1)) { + this.interpolateString(string.slice(1, -1)); + } else { + this.token('STRING', this.escapeLines(string)); + } + break; + default: + return 0; + } + if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) { + this.error("octal escape sequences " + string + " are not allowed"); + } + this.line += count(string, '\n'); + return string.length; + }; + + Lexer.prototype.heredocToken = function() { + var doc, heredoc, match, quote; + if (!(match = HEREDOC.exec(this.chunk))) { + return 0; + } + heredoc = match[0]; + quote = heredoc.charAt(0); + doc = this.sanitizeHeredoc(match[2], { + quote: quote, + indent: null + }); + if (quote === '"' && 0 <= doc.indexOf('#{')) { + this.interpolateString(doc, { + heredoc: true + }); + } else { + this.token('STRING', this.makeString(doc, quote, true)); + } + this.line += count(heredoc, '\n'); + return heredoc.length; + }; + + Lexer.prototype.commentToken = function() { + var comment, here, match; + if (!(match = this.chunk.match(COMMENT))) { + return 0; + } + comment = match[0], here = match[1]; + if (here) { + this.token('HERECOMMENT', this.sanitizeHeredoc(here, { + herecomment: true, + indent: Array(this.indent + 1).join(' ') + })); + } + this.line += count(comment, '\n'); + return comment.length; + }; + + Lexer.prototype.jsToken = function() { + var match, script; + if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) { + return 0; + } + this.token('JS', (script = match[0]).slice(1, -1)); + return script.length; + }; + + Lexer.prototype.regexToken = function() { + var flags, length, match, prev, regex, _ref2, _ref3; + if (this.chunk.charAt(0) !== '/') { + return 0; + } + if (match = HEREGEX.exec(this.chunk)) { + length = this.heregexToken(match); + this.line += count(match[0], '\n'); + return length; + } + prev = last(this.tokens); + if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) { + return 0; + } + if (!(match = REGEX.exec(this.chunk))) { + return 0; + } + _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2]; + if (regex.slice(0, 2) === '/*') { + this.error('regular expressions cannot begin with `*`'); + } + if (regex === '//') { + regex = '/(?:)/'; + } + this.token('REGEX', "" + regex + flags); + return match.length; + }; + + Lexer.prototype.heregexToken = function(match) { + var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5; + heregex = match[0], body = match[1], flags = match[2]; + if (0 > body.indexOf('#{')) { + re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/'); + if (re.match(/^\*/)) { + this.error('regular expressions cannot begin with `*`'); + } + this.token('REGEX', "/" + (re || '(?:)') + "/" + flags); + return heregex.length; + } + this.token('IDENTIFIER', 'RegExp'); + this.tokens.push(['CALL_START', '(']); + tokens = []; + _ref2 = this.interpolateString(body, { + regex: true + }); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1]; + if (tag === 'TOKENS') { + tokens.push.apply(tokens, value); + } else { + if (!(value = value.replace(HEREGEX_OMIT, ''))) { + continue; + } + value = value.replace(/\\/g, '\\\\'); + tokens.push(['STRING', this.makeString(value, '"', true)]); + } + tokens.push(['+', '+']); + } + tokens.pop(); + if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') { + this.tokens.push(['STRING', '""'], ['+', '+']); + } + (_ref5 = this.tokens).push.apply(_ref5, tokens); + if (flags) { + this.tokens.push([',', ','], ['STRING', '"' + flags + '"']); + } + this.token(')', ')'); + return heregex.length; + }; + + Lexer.prototype.lineToken = function() { + var diff, indent, match, noNewlines, prev, size; + if (!(match = MULTI_DENT.exec(this.chunk))) { + return 0; + } + indent = match[0]; + this.line += count(indent, '\n'); + this.seenFor = false; + prev = last(this.tokens, 1); + size = indent.length - 1 - indent.lastIndexOf('\n'); + noNewlines = this.unfinished(); + if (size - this.indebt === this.indent) { + if (noNewlines) { + this.suppressNewlines(); + } else { + this.newlineToken(); + } + return indent.length; + } + if (size > this.indent) { + if (noNewlines) { + this.indebt = size - this.indent; + this.suppressNewlines(); + return indent.length; + } + diff = size - this.indent + this.outdebt; + this.token('INDENT', diff); + this.indents.push(diff); + this.ends.push('OUTDENT'); + this.outdebt = this.indebt = 0; + } else { + this.indebt = 0; + this.outdentToken(this.indent - size, noNewlines); + } + this.indent = size; + return indent.length; + }; + + Lexer.prototype.outdentToken = function(moveOut, noNewlines) { + var dent, len; + while (moveOut > 0) { + len = this.indents.length - 1; + if (this.indents[len] === void 0) { + moveOut = 0; + } else if (this.indents[len] === this.outdebt) { + moveOut -= this.outdebt; + this.outdebt = 0; + } else if (this.indents[len] < this.outdebt) { + this.outdebt -= this.indents[len]; + moveOut -= this.indents[len]; + } else { + dent = this.indents.pop() - this.outdebt; + moveOut -= dent; + this.outdebt = 0; + this.pair('OUTDENT'); + this.token('OUTDENT', dent); + } + } + if (dent) { + this.outdebt -= moveOut; + } + while (this.value() === ';') { + this.tokens.pop(); + } + if (!(this.tag() === 'TERMINATOR' || noNewlines)) { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.whitespaceToken = function() { + var match, nline, prev; + if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) { + return 0; + } + prev = last(this.tokens); + if (prev) { + prev[match ? 'spaced' : 'newLine'] = true; + } + if (match) { + return match[0].length; + } else { + return 0; + } + }; + + Lexer.prototype.newlineToken = function() { + while (this.value() === ';') { + this.tokens.pop(); + } + if (this.tag() !== 'TERMINATOR') { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.suppressNewlines = function() { + if (this.value() === '\\') { + this.tokens.pop(); + } + return this; + }; + + Lexer.prototype.literalToken = function() { + var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5; + if (match = OPERATOR.exec(this.chunk)) { + value = match[0]; + if (CODE.test(value)) { + this.tagParameters(); + } + } else { + value = this.chunk.charAt(0); + } + tag = value; + prev = last(this.tokens); + if (value === '=' && prev) { + if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) { + this.error("reserved word \"" + (this.value()) + "\" can't be assigned"); + } + if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') { + prev[0] = 'COMPOUND_ASSIGN'; + prev[1] += '='; + return value.length; + } + } + if (value === ';') { + this.seenFor = false; + tag = 'TERMINATOR'; + } else if (__indexOf.call(MATH, value) >= 0) { + tag = 'MATH'; + } else if (__indexOf.call(COMPARE, value) >= 0) { + tag = 'COMPARE'; + } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) { + tag = 'COMPOUND_ASSIGN'; + } else if (__indexOf.call(UNARY, value) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(SHIFT, value) >= 0) { + tag = 'SHIFT'; + } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) { + tag = 'LOGIC'; + } else if (prev && !prev.spaced) { + if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) { + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + tag = 'CALL_START'; + } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) { + tag = 'INDEX_START'; + switch (prev[0]) { + case '?': + prev[0] = 'INDEX_SOAK'; + } + } + } + switch (value) { + case '(': + case '{': + case '[': + this.ends.push(INVERSES[value]); + break; + case ')': + case '}': + case ']': + this.pair(value); + } + this.token(tag, value); + return value.length; + }; + + Lexer.prototype.sanitizeHeredoc = function(doc, options) { + var attempt, herecomment, indent, match, _ref2; + indent = options.indent, herecomment = options.herecomment; + if (herecomment) { + if (HEREDOC_ILLEGAL.test(doc)) { + this.error("block comment cannot contain \"*/\", starting"); + } + if (doc.indexOf('\n') <= 0) { + return doc; + } + } else { + while (match = HEREDOC_INDENT.exec(doc)) { + attempt = match[1]; + if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) { + indent = attempt; + } + } + } + if (indent) { + doc = doc.replace(RegExp("\\n" + indent, "g"), '\n'); + } + if (!herecomment) { + doc = doc.replace(/^\n/, ''); + } + return doc; + }; + + Lexer.prototype.tagParameters = function() { + var i, stack, tok, tokens; + if (this.tag() !== ')') { + return this; + } + stack = []; + tokens = this.tokens; + i = tokens.length; + tokens[--i][0] = 'PARAM_END'; + while (tok = tokens[--i]) { + switch (tok[0]) { + case ')': + stack.push(tok); + break; + case '(': + case 'CALL_START': + if (stack.length) { + stack.pop(); + } else if (tok[0] === '(') { + tok[0] = 'PARAM_START'; + return this; + } else { + return this; + } + } + } + return this; + }; + + Lexer.prototype.closeIndentation = function() { + return this.outdentToken(this.indent); + }; + + Lexer.prototype.balancedString = function(str, end) { + var continueCount, i, letter, match, prev, stack, _i, _ref2; + continueCount = 0; + stack = [end]; + for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) { + if (continueCount) { + --continueCount; + continue; + } + switch (letter = str.charAt(i)) { + case '\\': + ++continueCount; + continue; + case end: + stack.pop(); + if (!stack.length) { + return str.slice(0, i + 1 || 9e9); + } + end = stack[stack.length - 1]; + continue; + } + if (end === '}' && (letter === '"' || letter === "'")) { + stack.push(end = letter); + } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) { + continueCount += match[0].length - 1; + } else if (end === '}' && letter === '{') { + stack.push(end = '}'); + } else if (end === '"' && prev === '#' && letter === '{') { + stack.push(end = '}'); + } + prev = letter; + } + return this.error("missing " + (stack.pop()) + ", starting"); + }; + + Lexer.prototype.interpolateString = function(str, options) { + var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4; + if (options == null) { + options = {}; + } + heredoc = options.heredoc, regex = options.regex; + tokens = []; + pi = 0; + i = -1; + while (letter = str.charAt(i += 1)) { + if (letter === '\\') { + i += 1; + continue; + } + if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) { + continue; + } + if (pi < i) { + tokens.push(['NEOSTRING', str.slice(pi, i)]); + } + inner = expr.slice(1, -1); + if (inner.length) { + nested = new Lexer().tokenize(inner, { + line: this.line, + rewrite: false + }); + nested.pop(); + if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') { + nested.shift(); + } + if (len = nested.length) { + if (len > 1) { + nested.unshift(['(', '(', this.line]); + nested.push([')', ')', this.line]); + } + tokens.push(['TOKENS', nested]); + } + } + i += expr.length; + pi = i + 1; + } + if ((i > pi && pi < str.length)) { + tokens.push(['NEOSTRING', str.slice(pi)]); + } + if (regex) { + return tokens; + } + if (!tokens.length) { + return this.token('STRING', '""'); + } + if (tokens[0][0] !== 'NEOSTRING') { + tokens.unshift(['', '']); + } + if (interpolated = tokens.length > 1) { + this.token('(', '('); + } + for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) { + _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1]; + if (i) { + this.token('+', '+'); + } + if (tag === 'TOKENS') { + (_ref4 = this.tokens).push.apply(_ref4, value); + } else { + this.token('STRING', this.makeString(value, '"', heredoc)); + } + } + if (interpolated) { + this.token(')', ')'); + } + return tokens; + }; + + Lexer.prototype.pair = function(tag) { + var size, wanted; + if (tag !== (wanted = last(this.ends))) { + if ('OUTDENT' !== wanted) { + this.error("unmatched " + tag); + } + this.indent -= size = last(this.indents); + this.outdentToken(size, true); + return this.pair(tag); + } + return this.ends.pop(); + }; + + Lexer.prototype.token = function(tag, value) { + return this.tokens.push([tag, value, this.line]); + }; + + Lexer.prototype.tag = function(index, tag) { + var tok; + return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]); + }; + + Lexer.prototype.value = function(index, val) { + var tok; + return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]); + }; + + Lexer.prototype.unfinished = function() { + var _ref2; + return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); + }; + + Lexer.prototype.escapeLines = function(str, heredoc) { + return str.replace(MULTILINER, heredoc ? '\\n' : ''); + }; + + Lexer.prototype.makeString = function(body, quote, heredoc) { + if (!body) { + return quote + quote; + } + body = body.replace(/\\([\s\S])/g, function(match, contents) { + if (contents === '\n' || contents === quote) { + return contents; + } else { + return match; + } + }); + body = body.replace(RegExp("" + quote, "g"), '\\$&'); + return quote + this.escapeLines(body, heredoc) + quote; + }; + + Lexer.prototype.error = function(message) { + throw SyntaxError("" + message + " on line " + (this.line + 1)); + }; + + return Lexer; + + })(); + + JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super']; + + COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']; + + COFFEE_ALIAS_MAP = { + and: '&&', + or: '||', + is: '==', + isnt: '!=', + not: '!', + yes: 'true', + no: 'false', + on: 'true', + off: 'false' + }; + + COFFEE_ALIASES = (function() { + var _results; + _results = []; + for (key in COFFEE_ALIAS_MAP) { + _results.push(key); + } + return _results; + })(); + + COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES); + + RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield']; + + STRICT_PROSCRIBED = ['arguments', 'eval']; + + JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED); + + exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED); + + exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED; + + IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/; + + NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; + + HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/; + + OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/; + + WHITESPACE = /^[^\n\S]+/; + + COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/; + + CODE = /^[-=]>/; + + MULTI_DENT = /^(?:\n[^\n\S]*)+/; + + SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; + + JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; + + REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/; + + HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/; + + HEREGEX_OMIT = /\s+(?:#.*)?/g; + + MULTILINER = /\n/g; + + HEREDOC_INDENT = /\n+([^\n\S]*)/g; + + HEREDOC_ILLEGAL = /\*\//; + + LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/; + + TRAILING_SPACES = /\s+$/; + + COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']; + + UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO']; + + LOGIC = ['&&', '||', '&', '|', '^']; + + SHIFT = ['<<', '>>', '>>>']; + + COMPARE = ['==', '!=', '<', '>', '<=', '>=']; + + MATH = ['*', '/', '%']; + + RELATION = ['IN', 'OF', 'INSTANCEOF']; + + BOOL = ['TRUE', 'FALSE']; + + NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']; + + NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING'); + + CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']; + + INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL', 'NULL', 'UNDEFINED'); + + LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/nodes.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/nodes.js new file mode 100644 index 000000000..799b68eb4 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/nodes.js @@ -0,0 +1,2986 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref, _ref1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + Scope = require('./scope').Scope; + + _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED; + + _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last; + + exports.extend = extend; + + YES = function() { + return true; + }; + + NO = function() { + return false; + }; + + THIS = function() { + return this; + }; + + NEGATE = function() { + this.negated = !this.negated; + return this; + }; + + exports.Base = Base = (function() { + + function Base() {} + + Base.prototype.compile = function(o, lvl) { + var node; + o = extend({}, o); + if (lvl) { + o.level = lvl; + } + node = this.unfoldSoak(o) || this; + node.tab = o.indent; + if (o.level === LEVEL_TOP || !node.isStatement(o)) { + return node.compileNode(o); + } else { + return node.compileClosure(o); + } + }; + + Base.prototype.compileClosure = function(o) { + if (this.jumps()) { + throw SyntaxError('cannot use a pure statement in an expression.'); + } + o.sharedScope = true; + return Closure.wrap(this).compileNode(o); + }; + + Base.prototype.cache = function(o, level, reused) { + var ref, sub; + if (!this.isComplex()) { + ref = level ? this.compile(o, level) : this; + return [ref, ref]; + } else { + ref = new Literal(reused || o.scope.freeVariable('ref')); + sub = new Assign(ref, this); + if (level) { + return [sub.compile(o, level), ref.value]; + } else { + return [sub, ref]; + } + } + }; + + Base.prototype.compileLoopReference = function(o, name) { + var src, tmp; + src = tmp = this.compile(o, LEVEL_LIST); + if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) { + src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src; + } + return [src, tmp]; + }; + + Base.prototype.makeReturn = function(res) { + var me; + me = this.unwrapAll(); + if (res) { + return new Call(new Literal("" + res + ".push"), [me]); + } else { + return new Return(me); + } + }; + + Base.prototype.contains = function(pred) { + var contains; + contains = false; + this.traverseChildren(false, function(node) { + if (pred(node)) { + contains = true; + return false; + } + }); + return contains; + }; + + Base.prototype.containsType = function(type) { + return this instanceof type || this.contains(function(node) { + return node instanceof type; + }); + }; + + Base.prototype.lastNonComment = function(list) { + var i; + i = list.length; + while (i--) { + if (!(list[i] instanceof Comment)) { + return list[i]; + } + } + return null; + }; + + Base.prototype.toString = function(idt, name) { + var tree; + if (idt == null) { + idt = ''; + } + if (name == null) { + name = this.constructor.name; + } + tree = '\n' + idt + name; + if (this.soak) { + tree += '?'; + } + this.eachChild(function(node) { + return tree += node.toString(idt + TAB); + }); + return tree; + }; + + Base.prototype.eachChild = function(func) { + var attr, child, _i, _j, _len, _len1, _ref2, _ref3; + if (!this.children) { + return this; + } + _ref2 = this.children; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + attr = _ref2[_i]; + if (this[attr]) { + _ref3 = flatten([this[attr]]); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + child = _ref3[_j]; + if (func(child) === false) { + return this; + } + } + } + } + return this; + }; + + Base.prototype.traverseChildren = function(crossScope, func) { + return this.eachChild(function(child) { + if (func(child) === false) { + return false; + } + return child.traverseChildren(crossScope, func); + }); + }; + + Base.prototype.invert = function() { + return new Op('!', this); + }; + + Base.prototype.unwrapAll = function() { + var node; + node = this; + while (node !== (node = node.unwrap())) { + continue; + } + return node; + }; + + Base.prototype.children = []; + + Base.prototype.isStatement = NO; + + Base.prototype.jumps = NO; + + Base.prototype.isComplex = YES; + + Base.prototype.isChainable = NO; + + Base.prototype.isAssignable = NO; + + Base.prototype.unwrap = THIS; + + Base.prototype.unfoldSoak = NO; + + Base.prototype.assigns = NO; + + return Base; + + })(); + + exports.Block = Block = (function(_super) { + + __extends(Block, _super); + + function Block(nodes) { + this.expressions = compact(flatten(nodes || [])); + } + + Block.prototype.children = ['expressions']; + + Block.prototype.push = function(node) { + this.expressions.push(node); + return this; + }; + + Block.prototype.pop = function() { + return this.expressions.pop(); + }; + + Block.prototype.unshift = function(node) { + this.expressions.unshift(node); + return this; + }; + + Block.prototype.unwrap = function() { + if (this.expressions.length === 1) { + return this.expressions[0]; + } else { + return this; + } + }; + + Block.prototype.isEmpty = function() { + return !this.expressions.length; + }; + + Block.prototype.isStatement = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.isStatement(o)) { + return true; + } + } + return false; + }; + + Block.prototype.jumps = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.jumps(o)) { + return exp; + } + } + }; + + Block.prototype.makeReturn = function(res) { + var expr, len; + len = this.expressions.length; + while (len--) { + expr = this.expressions[len]; + if (!(expr instanceof Comment)) { + this.expressions[len] = expr.makeReturn(res); + if (expr instanceof Return && !expr.expression) { + this.expressions.splice(len, 1); + } + break; + } + } + return this; + }; + + Block.prototype.compile = function(o, level) { + if (o == null) { + o = {}; + } + if (o.scope) { + return Block.__super__.compile.call(this, o, level); + } else { + return this.compileRoot(o); + } + }; + + Block.prototype.compileNode = function(o) { + var code, codes, node, top, _i, _len, _ref2; + this.tab = o.indent; + top = o.level === LEVEL_TOP; + codes = []; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + node = node.unwrapAll(); + node = node.unfoldSoak(o) || node; + if (node instanceof Block) { + codes.push(node.compileNode(o)); + } else if (top) { + node.front = true; + code = node.compile(o); + if (!node.isStatement(o)) { + code = "" + this.tab + code + ";"; + if (node instanceof Literal) { + code = "" + code + "\n"; + } + } + codes.push(code); + } else { + codes.push(node.compile(o, LEVEL_LIST)); + } + } + if (top) { + if (this.spaced) { + return "\n" + (codes.join('\n\n')) + "\n"; + } else { + return codes.join('\n'); + } + } + code = codes.join(', ') || 'void 0'; + if (codes.length > 1 && o.level >= LEVEL_LIST) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Block.prototype.compileRoot = function(o) { + var code, exp, i, prelude, preludeExps, rest; + o.indent = o.bare ? '' : TAB; + o.scope = new Scope(null, this, null); + o.level = LEVEL_TOP; + this.spaced = true; + prelude = ""; + if (!o.bare) { + preludeExps = (function() { + var _i, _len, _ref2, _results; + _ref2 = this.expressions; + _results = []; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + if (!(exp.unwrap() instanceof Comment)) { + break; + } + _results.push(exp); + } + return _results; + }).call(this); + rest = this.expressions.slice(preludeExps.length); + this.expressions = preludeExps; + if (preludeExps.length) { + prelude = "" + (this.compileNode(merge(o, { + indent: '' + }))) + "\n"; + } + this.expressions = rest; + } + code = this.compileWithDeclarations(o); + if (o.bare) { + return code; + } + return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n"; + }; + + Block.prototype.compileWithDeclarations = function(o) { + var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4; + code = post = ''; + _ref2 = this.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + exp = exp.unwrap(); + if (!(exp instanceof Comment || exp instanceof Literal)) { + break; + } + } + o = merge(o, { + level: LEVEL_TOP + }); + if (i) { + rest = this.expressions.splice(i, 9e9); + _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1]; + _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1]; + this.expressions = rest; + } + post = this.compileNode(o); + scope = o.scope; + if (scope.expressions === this) { + declars = o.scope.hasDeclarations(); + assigns = scope.hasAssignments; + if (declars || assigns) { + if (i) { + code += '\n'; + } + code += "" + this.tab + "var "; + if (declars) { + code += scope.declaredVariables().join(', '); + } + if (assigns) { + if (declars) { + code += ",\n" + (this.tab + TAB); + } + code += scope.assignedVariables().join(",\n" + (this.tab + TAB)); + } + code += ';\n'; + } + } + return code + post; + }; + + Block.wrap = function(nodes) { + if (nodes.length === 1 && nodes[0] instanceof Block) { + return nodes[0]; + } + return new Block(nodes); + }; + + return Block; + + })(Base); + + exports.Literal = Literal = (function(_super) { + + __extends(Literal, _super); + + function Literal(value) { + this.value = value; + } + + Literal.prototype.makeReturn = function() { + if (this.isStatement()) { + return this; + } else { + return Literal.__super__.makeReturn.apply(this, arguments); + } + }; + + Literal.prototype.isAssignable = function() { + return IDENTIFIER.test(this.value); + }; + + Literal.prototype.isStatement = function() { + var _ref2; + return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger'; + }; + + Literal.prototype.isComplex = NO; + + Literal.prototype.assigns = function(name) { + return name === this.value; + }; + + Literal.prototype.jumps = function(o) { + if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) { + return this; + } + if (this.value === 'continue' && !(o != null ? o.loop : void 0)) { + return this; + } + }; + + Literal.prototype.compileNode = function(o) { + var code, _ref2; + code = this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value; + if (this.isStatement()) { + return "" + this.tab + code + ";"; + } else { + return code; + } + }; + + Literal.prototype.toString = function() { + return ' "' + this.value + '"'; + }; + + return Literal; + + })(Base); + + exports.Undefined = (function(_super) { + + __extends(Undefined, _super); + + function Undefined() { + return Undefined.__super__.constructor.apply(this, arguments); + } + + Undefined.prototype.isAssignable = NO; + + Undefined.prototype.isComplex = NO; + + Undefined.prototype.compileNode = function(o) { + if (o.level >= LEVEL_ACCESS) { + return '(void 0)'; + } else { + return 'void 0'; + } + }; + + return Undefined; + + })(Base); + + exports.Null = (function(_super) { + + __extends(Null, _super); + + function Null() { + return Null.__super__.constructor.apply(this, arguments); + } + + Null.prototype.isAssignable = NO; + + Null.prototype.isComplex = NO; + + Null.prototype.compileNode = function() { + return "null"; + }; + + return Null; + + })(Base); + + exports.Bool = (function(_super) { + + __extends(Bool, _super); + + Bool.prototype.isAssignable = NO; + + Bool.prototype.isComplex = NO; + + Bool.prototype.compileNode = function() { + return this.val; + }; + + function Bool(val) { + this.val = val; + } + + return Bool; + + })(Base); + + exports.Return = Return = (function(_super) { + + __extends(Return, _super); + + function Return(expr) { + if (expr && !expr.unwrap().isUndefined) { + this.expression = expr; + } + } + + Return.prototype.children = ['expression']; + + Return.prototype.isStatement = YES; + + Return.prototype.makeReturn = THIS; + + Return.prototype.jumps = THIS; + + Return.prototype.compile = function(o, level) { + var expr, _ref2; + expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0; + if (expr && !(expr instanceof Return)) { + return expr.compile(o, level); + } else { + return Return.__super__.compile.call(this, o, level); + } + }; + + Return.prototype.compileNode = function(o) { + return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";"); + }; + + return Return; + + })(Base); + + exports.Value = Value = (function(_super) { + + __extends(Value, _super); + + function Value(base, props, tag) { + if (!props && base instanceof Value) { + return base; + } + this.base = base; + this.properties = props || []; + if (tag) { + this[tag] = true; + } + return this; + } + + Value.prototype.children = ['base', 'properties']; + + Value.prototype.add = function(props) { + this.properties = this.properties.concat(props); + return this; + }; + + Value.prototype.hasProperties = function() { + return !!this.properties.length; + }; + + Value.prototype.isArray = function() { + return !this.properties.length && this.base instanceof Arr; + }; + + Value.prototype.isComplex = function() { + return this.hasProperties() || this.base.isComplex(); + }; + + Value.prototype.isAssignable = function() { + return this.hasProperties() || this.base.isAssignable(); + }; + + Value.prototype.isSimpleNumber = function() { + return this.base instanceof Literal && SIMPLENUM.test(this.base.value); + }; + + Value.prototype.isString = function() { + return this.base instanceof Literal && IS_STRING.test(this.base.value); + }; + + Value.prototype.isAtomic = function() { + var node, _i, _len, _ref2; + _ref2 = this.properties.concat(this.base); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + if (node.soak || node instanceof Call) { + return false; + } + } + return true; + }; + + Value.prototype.isStatement = function(o) { + return !this.properties.length && this.base.isStatement(o); + }; + + Value.prototype.assigns = function(name) { + return !this.properties.length && this.base.assigns(name); + }; + + Value.prototype.jumps = function(o) { + return !this.properties.length && this.base.jumps(o); + }; + + Value.prototype.isObject = function(onlyGenerated) { + if (this.properties.length) { + return false; + } + return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated); + }; + + Value.prototype.isSplice = function() { + return last(this.properties) instanceof Slice; + }; + + Value.prototype.unwrap = function() { + if (this.properties.length) { + return this; + } else { + return this.base; + } + }; + + Value.prototype.cacheReference = function(o) { + var base, bref, name, nref; + name = last(this.properties); + if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { + return [this, this]; + } + base = new Value(this.base, this.properties.slice(0, -1)); + if (base.isComplex()) { + bref = new Literal(o.scope.freeVariable('base')); + base = new Value(new Parens(new Assign(bref, base))); + } + if (!name) { + return [base, bref]; + } + if (name.isComplex()) { + nref = new Literal(o.scope.freeVariable('name')); + name = new Index(new Assign(nref, name.index)); + nref = new Index(nref); + } + return [base.add(name), new Value(bref || base.base, [nref || name])]; + }; + + Value.prototype.compileNode = function(o) { + var code, prop, props, _i, _len; + this.base.front = this.front; + props = this.properties; + code = this.base.compile(o, props.length ? LEVEL_ACCESS : null); + if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) { + code = "" + code + "."; + } + for (_i = 0, _len = props.length; _i < _len; _i++) { + prop = props[_i]; + code += prop.compile(o); + } + return code; + }; + + Value.prototype.unfoldSoak = function(o) { + var result, + _this = this; + if (this.unfoldedSoak != null) { + return this.unfoldedSoak; + } + result = (function() { + var fst, i, ifn, prop, ref, snd, _i, _len, _ref2; + if (ifn = _this.base.unfoldSoak(o)) { + Array.prototype.push.apply(ifn.body.properties, _this.properties); + return ifn; + } + _ref2 = _this.properties; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + prop = _ref2[i]; + if (!prop.soak) { + continue; + } + prop.soak = false; + fst = new Value(_this.base, _this.properties.slice(0, i)); + snd = new Value(_this.base, _this.properties.slice(i)); + if (fst.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, fst)); + snd.base = ref; + } + return new If(new Existence(fst), snd, { + soak: true + }); + } + return null; + })(); + return this.unfoldedSoak = result || false; + }; + + return Value; + + })(Base); + + exports.Comment = Comment = (function(_super) { + + __extends(Comment, _super); + + function Comment(comment) { + this.comment = comment; + } + + Comment.prototype.isStatement = YES; + + Comment.prototype.makeReturn = THIS; + + Comment.prototype.compileNode = function(o, level) { + var code; + code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/\n"); + if ((level || o.level) === LEVEL_TOP) { + code = o.indent + code; + } + return code; + }; + + return Comment; + + })(Base); + + exports.Call = Call = (function(_super) { + + __extends(Call, _super); + + function Call(variable, args, soak) { + this.args = args != null ? args : []; + this.soak = soak; + this.isNew = false; + this.isSuper = variable === 'super'; + this.variable = this.isSuper ? null : variable; + } + + Call.prototype.children = ['variable', 'args']; + + Call.prototype.newInstance = function() { + var base, _ref2; + base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable; + if (base instanceof Call && !base.isNew) { + base.newInstance(); + } else { + this.isNew = true; + } + return this; + }; + + Call.prototype.superReference = function(o) { + var accesses, method, name; + method = o.scope.namedMethod(); + if (!method) { + throw SyntaxError('cannot call super outside of a function.'); + } + name = method.name; + if (name == null) { + throw SyntaxError('cannot call super on an anonymous function.'); + } + if (method.klass) { + accesses = [new Access(new Literal('__super__'))]; + if (method["static"]) { + accesses.push(new Access(new Literal('constructor'))); + } + accesses.push(new Access(new Literal(name))); + return (new Value(new Literal(method.klass), accesses)).compile(o); + } else { + return "" + name + ".__super__.constructor"; + } + }; + + Call.prototype.superThis = function(o) { + var method; + method = o.scope.method; + return (method && !method.klass && method.context) || "this"; + }; + + Call.prototype.unfoldSoak = function(o) { + var call, ifn, left, list, rite, _i, _len, _ref2, _ref3; + if (this.soak) { + if (this.variable) { + if (ifn = unfoldSoak(o, this, 'variable')) { + return ifn; + } + _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; + } else { + left = new Literal(this.superReference(o)); + rite = new Value(left); + } + rite = new Call(rite, this.args); + rite.isNew = this.isNew; + left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); + return new If(left, new Value(rite), { + soak: true + }); + } + call = this; + list = []; + while (true) { + if (call.variable instanceof Call) { + list.push(call); + call = call.variable; + continue; + } + if (!(call.variable instanceof Value)) { + break; + } + list.push(call); + if (!((call = call.variable.base) instanceof Call)) { + break; + } + } + _ref3 = list.reverse(); + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + call = _ref3[_i]; + if (ifn) { + if (call.variable instanceof Call) { + call.variable = ifn; + } else { + call.variable.base = ifn; + } + } + ifn = unfoldSoak(o, call, 'variable'); + } + return ifn; + }; + + Call.prototype.filterImplicitObjects = function(list) { + var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2; + nodes = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + node = list[_i]; + if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) { + nodes.push(node); + continue; + } + obj = null; + _ref2 = node.base.properties; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + prop = _ref2[_j]; + if (prop instanceof Assign || prop instanceof Comment) { + if (!obj) { + nodes.push(obj = new Obj(properties = [], true)); + } + properties.push(prop); + } else { + nodes.push(prop); + obj = null; + } + } + } + return nodes; + }; + + Call.prototype.compileNode = function(o) { + var arg, args, code, _ref2; + if ((_ref2 = this.variable) != null) { + _ref2.front = this.front; + } + if (code = Splat.compileSplattedArray(o, this.args, true)) { + return this.compileSplat(o, code); + } + args = this.filterImplicitObjects(this.args); + args = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + _results.push(arg.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (this.isSuper) { + return this.superReference(o) + (".call(" + (this.superThis(o)) + (args && ', ' + args) + ")"); + } else { + return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); + } + }; + + Call.prototype.compileSuper = function(args, o) { + return "" + (this.superReference(o)) + ".call(" + (this.superThis(o)) + (args.length ? ', ' : '') + args + ")"; + }; + + Call.prototype.compileSplat = function(o, splatArgs) { + var base, fun, idt, name, ref; + if (this.isSuper) { + return "" + (this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", " + splatArgs + ")"; + } + if (this.isNew) { + idt = this.tab + TAB; + return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args), t = typeof result;\n" + idt + "return t == \"object\" || t == \"function\" ? result || child : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})"; + } + base = new Value(this.variable); + if ((name = base.properties.pop()) && base.isComplex()) { + ref = o.scope.freeVariable('ref'); + fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o)); + } else { + fun = base.compile(o, LEVEL_ACCESS); + if (SIMPLENUM.test(fun)) { + fun = "(" + fun + ")"; + } + if (name) { + ref = fun; + fun += name.compile(o); + } else { + ref = 'null'; + } + } + return "" + fun + ".apply(" + ref + ", " + splatArgs + ")"; + }; + + return Call; + + })(Base); + + exports.Extends = Extends = (function(_super) { + + __extends(Extends, _super); + + function Extends(child, parent) { + this.child = child; + this.parent = parent; + } + + Extends.prototype.children = ['child', 'parent']; + + Extends.prototype.compile = function(o) { + return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o); + }; + + return Extends; + + })(Base); + + exports.Access = Access = (function(_super) { + + __extends(Access, _super); + + function Access(name, tag) { + this.name = name; + this.name.asKey = true; + this.soak = tag === 'soak'; + } + + Access.prototype.children = ['name']; + + Access.prototype.compile = function(o) { + var name; + name = this.name.compile(o); + if (IDENTIFIER.test(name)) { + return "." + name; + } else { + return "[" + name + "]"; + } + }; + + Access.prototype.isComplex = NO; + + return Access; + + })(Base); + + exports.Index = Index = (function(_super) { + + __extends(Index, _super); + + function Index(index) { + this.index = index; + } + + Index.prototype.children = ['index']; + + Index.prototype.compile = function(o) { + return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]"; + }; + + Index.prototype.isComplex = function() { + return this.index.isComplex(); + }; + + return Index; + + })(Base); + + exports.Range = Range = (function(_super) { + + __extends(Range, _super); + + Range.prototype.children = ['from', 'to']; + + function Range(from, to, tag) { + this.from = from; + this.to = to; + this.exclusive = tag === 'exclusive'; + this.equals = this.exclusive ? '' : '='; + } + + Range.prototype.compileVariables = function(o) { + var step, _ref2, _ref3, _ref4, _ref5; + o = merge(o, { + top: true + }); + _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1]; + _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1]; + if (step = del(o, 'step')) { + _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1]; + } + _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1]; + if (this.stepVar) { + return this.stepNum = this.stepVar.match(SIMPLENUM); + } + }; + + Range.prototype.compileNode = function(o) { + var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3; + if (!this.fromVar) { + this.compileVariables(o); + } + if (!o.index) { + return this.compileArray(o); + } + known = this.fromNum && this.toNum; + idx = del(o, 'index'); + idxName = del(o, 'name'); + namedIndex = idxName && idxName !== idx; + varPart = "" + idx + " = " + this.fromC; + if (this.toC !== this.toVar) { + varPart += ", " + this.toC; + } + if (this.step !== this.stepVar) { + varPart += ", " + this.step; + } + _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1]; + condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); + stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--"; + if (namedIndex) { + varPart = "" + idxName + " = " + varPart; + } + if (namedIndex) { + stepPart = "" + idxName + " = " + stepPart; + } + return "" + varPart + "; " + condPart + "; " + stepPart; + }; + + Range.prototype.compileArray = function(o) { + var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results; + if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { + range = (function() { + _results = []; + for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + if (this.exclusive) { + range.pop(); + } + return "[" + (range.join(', ')) + "]"; + } + idt = this.tab + TAB; + i = o.scope.freeVariable('i'); + result = o.scope.freeVariable('results'); + pre = "\n" + idt + result + " = [];"; + if (this.fromNum && this.toNum) { + o.index = i; + body = this.compileNode(o); + } else { + vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : ''); + cond = "" + this.fromVar + " <= " + this.toVar; + body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--"; + } + post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; + hasArgs = function(node) { + return node != null ? node.contains(function(n) { + return n instanceof Literal && n.value === 'arguments' && !n.asKey; + }) : void 0; + }; + if (hasArgs(this.from) || hasArgs(this.to)) { + args = ', arguments'; + } + return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")"; + }; + + return Range; + + })(Base); + + exports.Slice = Slice = (function(_super) { + + __extends(Slice, _super); + + Slice.prototype.children = ['range']; + + function Slice(range) { + this.range = range; + Slice.__super__.constructor.call(this); + } + + Slice.prototype.compileNode = function(o) { + var compiled, from, fromStr, to, toStr, _ref2; + _ref2 = this.range, to = _ref2.to, from = _ref2.from; + fromStr = from && from.compile(o, LEVEL_PAREN) || '0'; + compiled = to && to.compile(o, LEVEL_PAREN); + if (to && !(!this.range.exclusive && +compiled === -1)) { + toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? "" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), "" + compiled + " + 1 || 9e9")); + } + return ".slice(" + fromStr + (toStr || '') + ")"; + }; + + return Slice; + + })(Base); + + exports.Obj = Obj = (function(_super) { + + __extends(Obj, _super); + + function Obj(props, generated) { + this.generated = generated != null ? generated : false; + this.objects = this.properties = props || []; + } + + Obj.prototype.children = ['properties']; + + Obj.prototype.compileNode = function(o) { + var i, idt, indent, join, lastNoncom, node, obj, prop, propName, propNames, props, _i, _j, _len, _len1, _ref2; + props = this.properties; + propNames = []; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.isComplex()) { + prop = prop.variable; + } + if (prop != null) { + propName = prop.unwrapAll().value.toString(); + if (__indexOf.call(propNames, propName) >= 0) { + throw SyntaxError("multiple object literal properties named \"" + propName + "\""); + } + propNames.push(propName); + } + } + if (!props.length) { + return (this.front ? '({})' : '{}'); + } + if (this.generated) { + for (_j = 0, _len1 = props.length; _j < _len1; _j++) { + node = props[_j]; + if (node instanceof Value) { + throw new Error('cannot have an implicit value in an implicit object'); + } + } + } + idt = o.indent += TAB; + lastNoncom = this.lastNonComment(this.properties); + props = (function() { + var _k, _len2, _results; + _results = []; + for (i = _k = 0, _len2 = props.length; _k < _len2; i = ++_k) { + prop = props[i]; + join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; + indent = prop instanceof Comment ? '' : idt; + if (prop instanceof Value && prop["this"]) { + prop = new Assign(prop.properties[0].name, prop, 'object'); + } + if (!(prop instanceof Comment)) { + if (!(prop instanceof Assign)) { + prop = new Assign(prop, prop, 'object'); + } + (prop.variable.base || prop.variable).asKey = true; + } + _results.push(indent + prop.compile(o, LEVEL_TOP) + join); + } + return _results; + })(); + props = props.join(''); + obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; + if (this.front) { + return "(" + obj + ")"; + } else { + return obj; + } + }; + + Obj.prototype.assigns = function(name) { + var prop, _i, _len, _ref2; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.assigns(name)) { + return true; + } + } + return false; + }; + + return Obj; + + })(Base); + + exports.Arr = Arr = (function(_super) { + + __extends(Arr, _super); + + function Arr(objs) { + this.objects = objs || []; + } + + Arr.prototype.children = ['objects']; + + Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects; + + Arr.prototype.compileNode = function(o) { + var code, obj, objs; + if (!this.objects.length) { + return '[]'; + } + o.indent += TAB; + objs = this.filterImplicitObjects(this.objects); + if (code = Splat.compileSplattedArray(o, objs)) { + return code; + } + code = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = objs.length; _i < _len; _i++) { + obj = objs[_i]; + _results.push(obj.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (code.indexOf('\n') >= 0) { + return "[\n" + o.indent + code + "\n" + this.tab + "]"; + } else { + return "[" + code + "]"; + } + }; + + Arr.prototype.assigns = function(name) { + var obj, _i, _len, _ref2; + _ref2 = this.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj.assigns(name)) { + return true; + } + } + return false; + }; + + return Arr; + + })(Base); + + exports.Class = Class = (function(_super) { + + __extends(Class, _super); + + function Class(variable, parent, body) { + this.variable = variable; + this.parent = parent; + this.body = body != null ? body : new Block; + this.boundFuncs = []; + this.body.classBody = true; + } + + Class.prototype.children = ['variable', 'parent', 'body']; + + Class.prototype.determineName = function() { + var decl, tail; + if (!this.variable) { + return null; + } + decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value; + if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) { + throw SyntaxError("variable name may not be " + decl); + } + return decl && (decl = IDENTIFIER.test(decl) && decl); + }; + + Class.prototype.setContext = function(name) { + return this.body.traverseChildren(false, function(node) { + if (node.classBody) { + return false; + } + if (node instanceof Literal && node.value === 'this') { + return node.value = name; + } else if (node instanceof Code) { + node.klass = name; + if (node.bound) { + return node.context = name; + } + } + }); + }; + + Class.prototype.addBoundFunctions = function(o) { + var bvar, lhs, _i, _len, _ref2, _results; + if (this.boundFuncs.length) { + _ref2 = this.boundFuncs; + _results = []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + bvar = _ref2[_i]; + lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); + _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"))); + } + return _results; + } + }; + + Class.prototype.addProperties = function(node, name, o) { + var assign, base, exprs, func, props; + props = node.base.properties.slice(0); + exprs = (function() { + var _results; + _results = []; + while (assign = props.shift()) { + if (assign instanceof Assign) { + base = assign.variable.base; + delete assign.context; + func = assign.value; + if (base.value === 'constructor') { + if (this.ctor) { + throw new Error('cannot define more than one constructor in a class'); + } + if (func.bound) { + throw new Error('cannot define a constructor as a bound function'); + } + if (func instanceof Code) { + assign = this.ctor = func; + } else { + this.externalCtor = o.scope.freeVariable('class'); + assign = new Assign(new Literal(this.externalCtor), func); + } + } else { + if (assign.variable["this"]) { + func["static"] = true; + if (func.bound) { + func.context = name; + } + } else { + assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); + if (func instanceof Code && func.bound) { + this.boundFuncs.push(base); + func.bound = false; + } + } + } + } + _results.push(assign); + } + return _results; + }).call(this); + return compact(exprs); + }; + + Class.prototype.walkBody = function(name, o) { + var _this = this; + return this.traverseChildren(false, function(child) { + var exps, i, node, _i, _len, _ref2; + if (child instanceof Class) { + return false; + } + if (child instanceof Block) { + _ref2 = exps = child.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + node = _ref2[i]; + if (node instanceof Value && node.isObject(true)) { + exps[i] = _this.addProperties(node, name, o); + } + } + return child.expressions = exps = flatten(exps); + } + }); + }; + + Class.prototype.hoistDirectivePrologue = function() { + var expressions, index, node; + index = 0; + expressions = this.body.expressions; + while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) { + ++index; + } + return this.directives = expressions.splice(0, index); + }; + + Class.prototype.ensureConstructor = function(name) { + if (!this.ctor) { + this.ctor = new Code; + if (this.parent) { + this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)")); + } + if (this.externalCtor) { + this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); + } + this.ctor.body.makeReturn(); + this.body.expressions.unshift(this.ctor); + } + this.ctor.ctor = this.ctor.name = name; + this.ctor.klass = null; + return this.ctor.noReturn = true; + }; + + Class.prototype.compileNode = function(o) { + var call, decl, klass, lname, name, params, _ref2; + decl = this.determineName(); + name = decl || '_Class'; + if (name.reserved) { + name = "_" + name; + } + lname = new Literal(name); + this.hoistDirectivePrologue(); + this.setContext(name); + this.walkBody(name, o); + this.ensureConstructor(name); + this.body.spaced = true; + if (!(this.ctor instanceof Code)) { + this.body.expressions.unshift(this.ctor); + } + this.body.expressions.push(lname); + (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives); + this.addBoundFunctions(o); + call = Closure.wrap(this.body); + if (this.parent) { + this.superClass = new Literal(o.scope.freeVariable('super', false)); + this.body.expressions.unshift(new Extends(lname, this.superClass)); + call.args.push(this.parent); + params = call.variable.params || call.variable.base.params; + params.push(new Param(this.superClass)); + } + klass = new Parens(call, true); + if (this.variable) { + klass = new Assign(this.variable, klass); + } + return klass.compile(o); + }; + + return Class; + + })(Base); + + exports.Assign = Assign = (function(_super) { + + __extends(Assign, _super); + + function Assign(variable, value, context, options) { + var forbidden, name, _ref2; + this.variable = variable; + this.value = value; + this.context = context; + this.param = options && options.param; + this.subpattern = options && options.subpattern; + forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0); + if (forbidden && this.context !== 'object') { + throw SyntaxError("variable name may not be \"" + name + "\""); + } + } + + Assign.prototype.children = ['variable', 'value']; + + Assign.prototype.isStatement = function(o) { + return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0; + }; + + Assign.prototype.assigns = function(name) { + return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); + }; + + Assign.prototype.unfoldSoak = function(o) { + return unfoldSoak(o, this, 'variable'); + }; + + Assign.prototype.compileNode = function(o) { + var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5; + if (isValue = this.variable instanceof Value) { + if (this.variable.isArray() || this.variable.isObject()) { + return this.compilePatternMatch(o); + } + if (this.variable.isSplice()) { + return this.compileSplice(o); + } + if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') { + return this.compileConditional(o); + } + } + name = this.variable.compile(o, LEVEL_LIST); + if (!this.context) { + if (!(varBase = this.variable.unwrapAll()).isAssignable()) { + throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned."); + } + if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) { + if (this.param) { + o.scope.add(name, 'var'); + } else { + o.scope.find(name); + } + } + } + if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) { + if (match[1]) { + this.value.klass = match[1]; + } + this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5]; + } + val = this.value.compile(o, LEVEL_LIST); + if (this.context === 'object') { + return "" + name + ": " + val; + } + val = name + (" " + (this.context || '=') + " ") + val; + if (o.level <= LEVEL_LIST) { + return val; + } else { + return "(" + val + ")"; + } + }; + + Assign.prototype.compilePatternMatch = function(o) { + var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + top = o.level === LEVEL_TOP; + value = this.value; + objects = this.variable.base.objects; + if (!(olen = objects.length)) { + code = value.compile(o); + if (o.level >= LEVEL_OP) { + return "(" + code + ")"; + } else { + return code; + } + } + isObject = this.variable.isObject(); + if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { + if (obj instanceof Assign) { + _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value; + } else { + if (obj.base instanceof Parens) { + _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1]; + } else { + idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); + } + } + acc = IDENTIFIER.test(idx.unwrap().value || 0); + value = new Value(value); + value.properties.push(new (acc ? Access : Index)(idx)); + if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o))); + } + return new Assign(obj, value, null, { + param: this.param + }).compile(o, LEVEL_TOP); + } + vvar = value.compile(o, LEVEL_LIST); + assigns = []; + splat = false; + if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) { + assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar); + vvar = ref; + } + for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) { + obj = objects[i]; + idx = i; + if (isObject) { + if (obj instanceof Assign) { + _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value; + } else { + if (obj.base instanceof Parens) { + _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1]; + } else { + idx = obj["this"] ? obj.properties[0].name : obj; + } + } + } + if (!splat && obj instanceof Splat) { + name = obj.name.unwrap().value; + obj = obj.unwrap(); + val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i; + if (rest = olen - i - 1) { + ivar = o.scope.freeVariable('i'); + val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])"; + } else { + val += ") : []"; + } + val = new Literal(val); + splat = "" + ivar + "++"; + } else { + name = obj.unwrap().value; + if (obj instanceof Splat) { + obj = obj.name.compile(o); + throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "..."); + } + if (typeof idx === 'number') { + idx = new Literal(splat || idx); + acc = false; + } else { + acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); + } + val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]); + } + if ((name != null) && __indexOf.call(RESERVED, name) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o))); + } + assigns.push(new Assign(obj, val, null, { + param: this.param, + subpattern: true + }).compile(o, LEVEL_LIST)); + } + if (!(top || this.subpattern)) { + assigns.push(vvar); + } + code = assigns.join(', '); + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Assign.prototype.compileConditional = function(o) { + var left, right, _ref2; + _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1]; + if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { + throw new Error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been defined."); + } + if (__indexOf.call(this.context, "?") >= 0) { + o.isExistentialEquals = true; + } + return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o); + }; + + Assign.prototype.compileSplice = function(o) { + var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4; + _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive; + name = this.variable.compile(o); + _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1]; + if (to) { + if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) { + to = +to.compile(o) - +fromRef; + if (!exclusive) { + to += 1; + } + } else { + to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef; + if (!exclusive) { + to += ' + 1'; + } + } + } else { + to = "9e9"; + } + _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1]; + code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef; + if (o.level > LEVEL_TOP) { + return "(" + code + ")"; + } else { + return code; + } + }; + + return Assign; + + })(Base); + + exports.Code = Code = (function(_super) { + + __extends(Code, _super); + + function Code(params, body, tag) { + this.params = params || []; + this.body = body || new Block; + this.bound = tag === 'boundfunc'; + if (this.bound) { + this.context = '_this'; + } + } + + Code.prototype.children = ['params', 'body']; + + Code.prototype.isStatement = function() { + return !!this.ctor; + }; + + Code.prototype.jumps = NO; + + Code.prototype.compileNode = function(o) { + var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + o.scope = new Scope(o.scope, this.body, this); + o.scope.shared = del(o, 'sharedScope'); + o.indent += TAB; + delete o.bare; + delete o.isExistentialEquals; + params = []; + exprs = []; + _ref2 = this.paramNames(); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + name = _ref2[_i]; + if (!o.scope.check(name)) { + o.scope.parameter(name); + } + } + _ref3 = this.params; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + param = _ref3[_j]; + if (!param.splat) { + continue; + } + _ref4 = this.params; + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + p = _ref4[_k].name; + if (p["this"]) { + p = p.properties[0].name; + } + if (p.value) { + o.scope.add(p.value, 'var', true); + } + } + splats = new Assign(new Value(new Arr((function() { + var _l, _len3, _ref5, _results; + _ref5 = this.params; + _results = []; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + p = _ref5[_l]; + _results.push(p.asReference(o)); + } + return _results; + }).call(this))), new Value(new Literal('arguments'))); + break; + } + _ref5 = this.params; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + param = _ref5[_l]; + if (param.isComplex()) { + val = ref = param.asReference(o); + if (param.value) { + val = new Op('?', ref, param.value); + } + exprs.push(new Assign(new Value(param.name), val, '=', { + param: true + })); + } else { + ref = param; + if (param.value) { + lit = new Literal(ref.name.value + ' == null'); + val = new Assign(new Value(param.name), param.value, '='); + exprs.push(new If(lit, val)); + } + } + if (!splats) { + params.push(ref); + } + } + wasEmpty = this.body.isEmpty(); + if (splats) { + exprs.unshift(splats); + } + if (exprs.length) { + (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs); + } + for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { + p = params[i]; + o.scope.parameter(params[i] = p.compile(o)); + } + uniqs = []; + _ref7 = this.paramNames(); + for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) { + name = _ref7[_n]; + if (__indexOf.call(uniqs, name) >= 0) { + throw SyntaxError("multiple parameters named '" + name + "'"); + } + uniqs.push(name); + } + if (!(wasEmpty || this.noReturn)) { + this.body.makeReturn(); + } + if (this.bound) { + if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) { + this.bound = this.context = o.scope.parent.method.context; + } else if (!this["static"]) { + o.scope.parent.assign('_this', 'this'); + } + } + idt = o.indent; + code = 'function'; + if (this.ctor) { + code += ' ' + this.name; + } + code += '(' + params.join(', ') + ') {'; + if (!this.body.isEmpty()) { + code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab; + } + code += '}'; + if (this.ctor) { + return this.tab + code; + } + if (this.front || (o.level >= LEVEL_ACCESS)) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Code.prototype.paramNames = function() { + var names, param, _i, _len, _ref2; + names = []; + _ref2 = this.params; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + names.push.apply(names, param.names()); + } + return names; + }; + + Code.prototype.traverseChildren = function(crossScope, func) { + if (crossScope) { + return Code.__super__.traverseChildren.call(this, crossScope, func); + } + }; + + return Code; + + })(Base); + + exports.Param = Param = (function(_super) { + + __extends(Param, _super); + + function Param(name, value, splat) { + var _ref2; + this.name = name; + this.value = value; + this.splat = splat; + if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("parameter name \"" + name + "\" is not allowed"); + } + } + + Param.prototype.children = ['name', 'value']; + + Param.prototype.compile = function(o) { + return this.name.compile(o, LEVEL_LIST); + }; + + Param.prototype.asReference = function(o) { + var node; + if (this.reference) { + return this.reference; + } + node = this.name; + if (node["this"]) { + node = node.properties[0].name; + if (node.value.reserved) { + node = new Literal(o.scope.freeVariable(node.value)); + } + } else if (node.isComplex()) { + node = new Literal(o.scope.freeVariable('arg')); + } + node = new Value(node); + if (this.splat) { + node = new Splat(node); + } + return this.reference = node; + }; + + Param.prototype.isComplex = function() { + return this.name.isComplex(); + }; + + Param.prototype.names = function(name) { + var atParam, names, obj, _i, _len, _ref2; + if (name == null) { + name = this.name; + } + atParam = function(obj) { + var value; + value = obj.properties[0].name.value; + if (value.reserved) { + return []; + } else { + return [value]; + } + }; + if (name instanceof Literal) { + return [name.value]; + } + if (name instanceof Value) { + return atParam(name); + } + names = []; + _ref2 = name.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj instanceof Assign) { + names.push(obj.value.unwrap().value); + } else if (obj instanceof Splat) { + names.push(obj.name.unwrap().value); + } else if (obj instanceof Value) { + if (obj.isArray() || obj.isObject()) { + names.push.apply(names, this.names(obj.base)); + } else if (obj["this"]) { + names.push.apply(names, atParam(obj)); + } else { + names.push(obj.base.value); + } + } else { + throw SyntaxError("illegal parameter " + (obj.compile())); + } + } + return names; + }; + + return Param; + + })(Base); + + exports.Splat = Splat = (function(_super) { + + __extends(Splat, _super); + + Splat.prototype.children = ['name']; + + Splat.prototype.isAssignable = YES; + + function Splat(name) { + this.name = name.compile ? name : new Literal(name); + } + + Splat.prototype.assigns = function(name) { + return this.name.assigns(name); + }; + + Splat.prototype.compile = function(o) { + if (this.index != null) { + return this.compileParam(o); + } else { + return this.name.compile(o); + } + }; + + Splat.prototype.unwrap = function() { + return this.name; + }; + + Splat.compileSplattedArray = function(o, list, apply) { + var args, base, code, i, index, node, _i, _len; + index = -1; + while ((node = list[++index]) && !(node instanceof Splat)) { + continue; + } + if (index >= list.length) { + return ''; + } + if (list.length === 1) { + code = list[0].compile(o, LEVEL_LIST); + if (apply) { + return code; + } + return "" + (utility('slice')) + ".call(" + code + ")"; + } + args = list.slice(index); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + node = args[i]; + code = node.compile(o, LEVEL_LIST); + args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]"; + } + if (index === 0) { + return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")"); + } + base = (function() { + var _j, _len1, _ref2, _results; + _ref2 = list.slice(0, index); + _results = []; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + node = _ref2[_j]; + _results.push(node.compile(o, LEVEL_LIST)); + } + return _results; + })(); + return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")"; + }; + + return Splat; + + })(Base); + + exports.While = While = (function(_super) { + + __extends(While, _super); + + function While(condition, options) { + this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; + this.guard = options != null ? options.guard : void 0; + } + + While.prototype.children = ['condition', 'guard', 'body']; + + While.prototype.isStatement = YES; + + While.prototype.makeReturn = function(res) { + if (res) { + return While.__super__.makeReturn.apply(this, arguments); + } else { + this.returns = !this.jumps({ + loop: true + }); + return this; + } + }; + + While.prototype.addBody = function(body) { + this.body = body; + return this; + }; + + While.prototype.jumps = function() { + var expressions, node, _i, _len; + expressions = this.body.expressions; + if (!expressions.length) { + return false; + } + for (_i = 0, _len = expressions.length; _i < _len; _i++) { + node = expressions[_i]; + if (node.jumps({ + loop: true + })) { + return node; + } + } + return false; + }; + + While.prototype.compileNode = function(o) { + var body, code, rvar, set; + o.indent += TAB; + set = ''; + body = this.body; + if (body.isEmpty()) { + body = ''; + } else { + if (this.returns) { + body.makeReturn(rvar = o.scope.freeVariable('results')); + set = "" + this.tab + rvar + " = [];\n"; + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab; + } + code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}"); + if (this.returns) { + code += "\n" + this.tab + "return " + rvar + ";"; + } + return code; + }; + + return While; + + })(Base); + + exports.Op = Op = (function(_super) { + var CONVERSIONS, INVERSIONS; + + __extends(Op, _super); + + function Op(op, first, second, flip) { + if (op === 'in') { + return new In(first, second); + } + if (op === 'do') { + return this.generateDo(first); + } + if (op === 'new') { + if (first instanceof Call && !first["do"] && !first.isNew) { + return first.newInstance(); + } + if (first instanceof Code && first.bound || first["do"]) { + first = new Parens(first); + } + } + this.operator = CONVERSIONS[op] || op; + this.first = first; + this.second = second; + this.flip = !!flip; + return this; + } + + CONVERSIONS = { + '==': '===', + '!=': '!==', + 'of': 'in' + }; + + INVERSIONS = { + '!==': '===', + '===': '!==' + }; + + Op.prototype.children = ['first', 'second']; + + Op.prototype.isSimpleNumber = NO; + + Op.prototype.isUnary = function() { + return !this.second; + }; + + Op.prototype.isComplex = function() { + var _ref2; + return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex(); + }; + + Op.prototype.isChainable = function() { + var _ref2; + return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!=='; + }; + + Op.prototype.invert = function() { + var allInvertable, curr, fst, op, _ref2; + if (this.isChainable() && this.first.isChainable()) { + allInvertable = true; + curr = this; + while (curr && curr.operator) { + allInvertable && (allInvertable = curr.operator in INVERSIONS); + curr = curr.first; + } + if (!allInvertable) { + return new Parens(this).invert(); + } + curr = this; + while (curr && curr.operator) { + curr.invert = !curr.invert; + curr.operator = INVERSIONS[curr.operator]; + curr = curr.first; + } + return this; + } else if (op = INVERSIONS[this.operator]) { + this.operator = op; + if (this.first.unwrap() instanceof Op) { + this.first.invert(); + } + return this; + } else if (this.second) { + return new Parens(this).invert(); + } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { + return fst; + } else { + return new Op('!', this); + } + }; + + Op.prototype.unfoldSoak = function(o) { + var _ref2; + return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); + }; + + Op.prototype.generateDo = function(exp) { + var call, func, param, passedParams, ref, _i, _len, _ref2; + passedParams = []; + func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; + _ref2 = func.params || []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + if (param.value) { + passedParams.push(param.value); + delete param.value; + } else { + passedParams.push(param); + } + } + call = new Call(exp, passedParams); + call["do"] = true; + return call; + }; + + Op.prototype.compileNode = function(o) { + var code, isChain, _ref2, _ref3; + isChain = this.isChainable() && this.first.isChainable(); + if (!isChain) { + this.first.front = this.front; + } + if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { + throw SyntaxError('delete operand may not be argument or var'); + } + if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) { + throw SyntaxError('prefix increment/decrement may not have eval or arguments operand'); + } + if (this.isUnary()) { + return this.compileUnary(o); + } + if (isChain) { + return this.compileChain(o); + } + if (this.operator === '?') { + return this.compileExistence(o); + } + code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP); + if (o.level <= LEVEL_OP) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Op.prototype.compileChain = function(o) { + var code, fst, shared, _ref2; + _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; + fst = this.first.compile(o, LEVEL_OP); + code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP)); + return "(" + code + ")"; + }; + + Op.prototype.compileExistence = function(o) { + var fst, ref; + if (this.first.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, this.first)); + } else { + fst = this.first; + ref = fst; + } + return new If(new Existence(fst), ref, { + type: 'if' + }).addElse(this.second).compile(o); + }; + + Op.prototype.compileUnary = function(o) { + var op, parts, plusMinus; + if (o.level >= LEVEL_ACCESS) { + return (new Parens(this)).compile(o); + } + parts = [op = this.operator]; + plusMinus = op === '+' || op === '-'; + if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { + parts.push(' '); + } + if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) { + this.first = new Parens(this.first); + } + parts.push(this.first.compile(o, LEVEL_OP)); + if (this.flip) { + parts.reverse(); + } + return parts.join(''); + }; + + Op.prototype.toString = function(idt) { + return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); + }; + + return Op; + + })(Base); + + exports.In = In = (function(_super) { + + __extends(In, _super); + + function In(object, array) { + this.object = object; + this.array = array; + } + + In.prototype.children = ['object', 'array']; + + In.prototype.invert = NEGATE; + + In.prototype.compileNode = function(o) { + var hasSplat, obj, _i, _len, _ref2; + if (this.array instanceof Value && this.array.isArray()) { + _ref2 = this.array.base.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (!(obj instanceof Splat)) { + continue; + } + hasSplat = true; + break; + } + if (!hasSplat) { + return this.compileOrTest(o); + } + } + return this.compileLoopTest(o); + }; + + In.prototype.compileOrTest = function(o) { + var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3; + if (this.array.base.objects.length === 0) { + return "" + (!!this.negated); + } + _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1]; + _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; + tests = (function() { + var _i, _len, _ref4, _results; + _ref4 = this.array.base.objects; + _results = []; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + item = _ref4[i]; + _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS)); + } + return _results; + }).call(this); + tests = tests.join(cnj); + if (o.level < LEVEL_OP) { + return tests; + } else { + return "(" + tests + ")"; + } + }; + + In.prototype.compileLoopTest = function(o) { + var code, ref, sub, _ref2; + _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1]; + code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0'); + if (sub === ref) { + return code; + } + code = sub + ', ' + code; + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + In.prototype.toString = function(idt) { + return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); + }; + + return In; + + })(Base); + + exports.Try = Try = (function(_super) { + + __extends(Try, _super); + + function Try(attempt, error, recovery, ensure) { + this.attempt = attempt; + this.error = error; + this.recovery = recovery; + this.ensure = ensure; + } + + Try.prototype.children = ['attempt', 'recovery', 'ensure']; + + Try.prototype.isStatement = YES; + + Try.prototype.jumps = function(o) { + var _ref2; + return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0); + }; + + Try.prototype.makeReturn = function(res) { + if (this.attempt) { + this.attempt = this.attempt.makeReturn(res); + } + if (this.recovery) { + this.recovery = this.recovery.makeReturn(res); + } + return this; + }; + + Try.prototype.compileNode = function(o) { + var catchPart, ensurePart, errorPart, tryPart; + o.indent += TAB; + errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; + tryPart = this.attempt.compile(o, LEVEL_TOP); + catchPart = (function() { + var _ref2; + if (this.recovery) { + if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("catch variable may not be \"" + this.error.value + "\""); + } + if (!o.scope.check(this.error.value)) { + o.scope.add(this.error.value, 'param'); + } + return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"; + } else if (!(this.ensure || this.recovery)) { + return ' catch (_error) {}'; + } + }).call(this); + ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : ''; + return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart; + }; + + return Try; + + })(Base); + + exports.Throw = Throw = (function(_super) { + + __extends(Throw, _super); + + function Throw(expression) { + this.expression = expression; + } + + Throw.prototype.children = ['expression']; + + Throw.prototype.isStatement = YES; + + Throw.prototype.jumps = NO; + + Throw.prototype.makeReturn = THIS; + + Throw.prototype.compileNode = function(o) { + return this.tab + ("throw " + (this.expression.compile(o)) + ";"); + }; + + return Throw; + + })(Base); + + exports.Existence = Existence = (function(_super) { + + __extends(Existence, _super); + + function Existence(expression) { + this.expression = expression; + } + + Existence.prototype.children = ['expression']; + + Existence.prototype.invert = NEGATE; + + Existence.prototype.compileNode = function(o) { + var cmp, cnj, code, _ref2; + this.expression.front = this.front; + code = this.expression.compile(o, LEVEL_OP); + if (IDENTIFIER.test(code) && !o.scope.check(code)) { + _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1]; + code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; + } else { + code = "" + code + " " + (this.negated ? '==' : '!=') + " null"; + } + if (o.level <= LEVEL_COND) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Existence; + + })(Base); + + exports.Parens = Parens = (function(_super) { + + __extends(Parens, _super); + + function Parens(body) { + this.body = body; + } + + Parens.prototype.children = ['body']; + + Parens.prototype.unwrap = function() { + return this.body; + }; + + Parens.prototype.isComplex = function() { + return this.body.isComplex(); + }; + + Parens.prototype.compileNode = function(o) { + var bare, code, expr; + expr = this.body.unwrap(); + if (expr instanceof Value && expr.isAtomic()) { + expr.front = this.front; + return expr.compile(o); + } + code = expr.compile(o, LEVEL_PAREN); + bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns)); + if (bare) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Parens; + + })(Base); + + exports.For = For = (function(_super) { + + __extends(For, _super); + + function For(body, source) { + var _ref2; + this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; + this.body = Block.wrap([body]); + this.own = !!source.own; + this.object = !!source.object; + if (this.object) { + _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1]; + } + if (this.index instanceof Value) { + throw SyntaxError('index cannot be a pattern matching expression'); + } + this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; + this.pattern = this.name instanceof Value; + if (this.range && this.index) { + throw SyntaxError('indexes do not apply to range loops'); + } + if (this.range && this.pattern) { + throw SyntaxError('cannot pattern match over range loops'); + } + this.returns = false; + } + + For.prototype.children = ['body', 'source', 'guard', 'step']; + + For.prototype.compileNode = function(o) { + var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2; + body = Block.wrap([this.body]); + lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0; + if (lastJumps && lastJumps instanceof Return) { + this.returns = false; + } + source = this.range ? this.source.base : this.source; + scope = o.scope; + name = this.name && this.name.compile(o, LEVEL_LIST); + index = this.index && this.index.compile(o, LEVEL_LIST); + if (name && !this.pattern) { + scope.find(name); + } + if (index) { + scope.find(index); + } + if (this.returns) { + rvar = scope.freeVariable('results'); + } + ivar = (this.object && index) || scope.freeVariable('i'); + kvar = (this.range && name) || index || ivar; + kvarAssign = kvar !== ivar ? "" + kvar + " = " : ""; + if (this.step && !this.range) { + stepvar = scope.freeVariable("step"); + } + if (this.pattern) { + name = ivar; + } + varPart = ''; + guardPart = ''; + defPart = ''; + idt1 = this.tab + TAB; + if (this.range) { + forPart = source.compile(merge(o, { + index: ivar, + name: name, + step: this.step + })); + } else { + svar = this.source.compile(o, LEVEL_LIST); + if ((name || this.own) && !IDENTIFIER.test(svar)) { + defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n"; + svar = ref; + } + if (name && !this.pattern) { + namePart = "" + name + " = " + svar + "[" + kvar + "]"; + } + if (!this.object) { + lvar = scope.freeVariable('len'); + forVarPart = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; + if (this.step) { + forVarPart += ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)); + } + stepPart = "" + kvarAssign + (this.step ? "" + ivar + " += " + stepvar : (kvar !== ivar ? "++" + ivar : "" + ivar + "++")); + forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart; + } + } + if (this.returns) { + resultPart = "" + this.tab + rvar + " = [];\n"; + returnResult = "\n" + this.tab + "return " + rvar + ";"; + body.makeReturn(rvar); + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + if (this.pattern) { + body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]"))); + } + defPart += this.pluckDirectCall(o, body); + if (namePart) { + varPart = "\n" + idt1 + namePart + ";"; + } + if (this.object) { + forPart = "" + kvar + " in " + svar; + if (this.own) { + guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;"; + } + } + body = body.compile(merge(o, { + indent: idt1 + }), LEVEL_TOP); + if (body) { + body = '\n' + body + '\n'; + } + return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || ''); + }; + + For.prototype.pluckDirectCall = function(o, body) { + var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + defs = ''; + _ref2 = body.expressions; + for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) { + expr = _ref2[idx]; + expr = expr.unwrapAll(); + if (!(expr instanceof Call)) { + continue; + } + val = expr.variable.unwrapAll(); + if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) { + continue; + } + fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val; + ref = new Literal(o.scope.freeVariable('fn')); + base = new Value(ref); + if (val.base) { + _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1]; + } + body.expressions[idx] = new Call(base, expr.args); + defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'; + } + return defs; + }; + + return For; + + })(While); + + exports.Switch = Switch = (function(_super) { + + __extends(Switch, _super); + + function Switch(subject, cases, otherwise) { + this.subject = subject; + this.cases = cases; + this.otherwise = otherwise; + } + + Switch.prototype.children = ['subject', 'cases', 'otherwise']; + + Switch.prototype.isStatement = YES; + + Switch.prototype.jumps = function(o) { + var block, conds, _i, _len, _ref2, _ref3, _ref4; + if (o == null) { + o = { + block: true + }; + } + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1]; + if (block.jumps(o)) { + return block; + } + } + return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0; + }; + + Switch.prototype.makeReturn = function(res) { + var pair, _i, _len, _ref2, _ref3; + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + pair = _ref2[_i]; + pair[1].makeReturn(res); + } + if (res) { + this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); + } + if ((_ref3 = this.otherwise) != null) { + _ref3.makeReturn(res); + } + return this; + }; + + Switch.prototype.compileNode = function(o) { + var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5; + idt1 = o.indent + TAB; + idt2 = o.indent = idt1 + TAB; + code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n"); + _ref3 = this.cases; + for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { + _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1]; + _ref5 = flatten([conditions]); + for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) { + cond = _ref5[_j]; + if (!this.subject) { + cond = cond.invert(); + } + code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n"); + } + if (body = block.compile(o, LEVEL_TOP)) { + code += body + '\n'; + } + if (i === this.cases.length - 1 && !this.otherwise) { + break; + } + expr = this.lastNonComment(block.expressions); + if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) { + continue; + } + code += idt2 + 'break;\n'; + } + if (this.otherwise && this.otherwise.expressions.length) { + code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n"); + } + return code + this.tab + '}'; + }; + + return Switch; + + })(Base); + + exports.If = If = (function(_super) { + + __extends(If, _super); + + function If(condition, body, options) { + this.body = body; + if (options == null) { + options = {}; + } + this.condition = options.type === 'unless' ? condition.invert() : condition; + this.elseBody = null; + this.isChain = false; + this.soak = options.soak; + } + + If.prototype.children = ['condition', 'body', 'elseBody']; + + If.prototype.bodyNode = function() { + var _ref2; + return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.elseBodyNode = function() { + var _ref2; + return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.addElse = function(elseBody) { + if (this.isChain) { + this.elseBodyNode().addElse(elseBody); + } else { + this.isChain = elseBody instanceof If; + this.elseBody = this.ensureBlock(elseBody); + } + return this; + }; + + If.prototype.isStatement = function(o) { + var _ref2; + return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0); + }; + + If.prototype.jumps = function(o) { + var _ref2; + return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0); + }; + + If.prototype.compileNode = function(o) { + if (this.isStatement(o)) { + return this.compileStatement(o); + } else { + return this.compileExpression(o); + } + }; + + If.prototype.makeReturn = function(res) { + if (res) { + this.elseBody || (this.elseBody = new Block([new Literal('void 0')])); + } + this.body && (this.body = new Block([this.body.makeReturn(res)])); + this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)])); + return this; + }; + + If.prototype.ensureBlock = function(node) { + if (node instanceof Block) { + return node; + } else { + return new Block([node]); + } + }; + + If.prototype.compileStatement = function(o) { + var body, child, cond, exeq, ifPart; + child = del(o, 'chainChild'); + exeq = del(o, 'isExistentialEquals'); + if (exeq) { + return new If(this.condition.invert(), this.elseBodyNode(), { + type: 'if' + }).compile(o); + } + cond = this.condition.compile(o, LEVEL_PAREN); + o.indent += TAB; + body = this.ensureBlock(this.body); + ifPart = "if (" + cond + ") {\n" + (body.compile(o)) + "\n" + this.tab + "}"; + if (!child) { + ifPart = this.tab + ifPart; + } + if (!this.elseBody) { + return ifPart; + } + return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"); + }; + + If.prototype.compileExpression = function(o) { + var alt, body, code, cond; + cond = this.condition.compile(o, LEVEL_COND); + body = this.bodyNode().compile(o, LEVEL_LIST); + alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0'; + code = "" + cond + " ? " + body + " : " + alt; + if (o.level >= LEVEL_COND) { + return "(" + code + ")"; + } else { + return code; + } + }; + + If.prototype.unfoldSoak = function() { + return this.soak && this; + }; + + return If; + + })(Base); + + Closure = { + wrap: function(expressions, statement, noReturn) { + var args, call, func, mentionsArgs, meth; + if (expressions.jumps()) { + return expressions; + } + func = new Code([], Block.wrap([expressions])); + args = []; + if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) { + meth = new Literal(mentionsArgs ? 'apply' : 'call'); + args = [new Literal('this')]; + if (mentionsArgs) { + args.push(new Literal('arguments')); + } + func = new Value(func, [new Access(meth)]); + } + func.noReturn = noReturn; + call = new Call(func, args); + if (statement) { + return Block.wrap([call]); + } else { + return call; + } + }, + literalArgs: function(node) { + return node instanceof Literal && node.value === 'arguments' && !node.asKey; + }, + literalThis: function(node) { + return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); + } + }; + + unfoldSoak = function(o, parent, name) { + var ifn; + if (!(ifn = parent[name].unfoldSoak(o))) { + return; + } + parent[name] = ifn.body; + ifn.body = new Value(parent); + return ifn; + }; + + UTILITIES = { + "extends": function() { + return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"; + }, + bind: function() { + return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }'; + }, + indexOf: function() { + return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; + }, + hasProp: function() { + return '{}.hasOwnProperty'; + }, + slice: function() { + return '[].slice'; + } + }; + + LEVEL_TOP = 1; + + LEVEL_PAREN = 2; + + LEVEL_LIST = 3; + + LEVEL_COND = 4; + + LEVEL_OP = 5; + + LEVEL_ACCESS = 6; + + TAB = ' '; + + IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"; + + IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$"); + + SIMPLENUM = /^[+-]?\d+$/; + + METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$"); + + IS_STRING = /^['"]/; + + utility = function(name) { + var ref; + ref = "__" + name; + Scope.root.assign(ref, UTILITIES[name]()); + return ref; + }; + + multident = function(code, tab) { + code = code.replace(/\n/g, '$&' + tab); + return code.replace(/\s+$/, ''); + }; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/optparse.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/optparse.js new file mode 100644 index 000000000..d7fda40a3 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/optparse.js @@ -0,0 +1,138 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; + + exports.OptionParser = OptionParser = (function() { + + function OptionParser(rules, banner) { + this.banner = banner; + this.rules = buildRules(rules); + } + + OptionParser.prototype.parse = function(args) { + var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref; + options = { + "arguments": [] + }; + skippingArgument = false; + originalArgs = args; + args = normalizeArguments(args); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + arg = args[i]; + if (skippingArgument) { + skippingArgument = false; + continue; + } + if (arg === '--') { + pos = originalArgs.indexOf('--'); + options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); + break; + } + isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); + seenNonOptionArg = options["arguments"].length > 0; + if (!seenNonOptionArg) { + matchedRule = false; + _ref = this.rules; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + rule = _ref[_j]; + if (rule.shortFlag === arg || rule.longFlag === arg) { + value = true; + if (rule.hasArgument) { + skippingArgument = true; + value = args[i + 1]; + } + options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; + matchedRule = true; + break; + } + } + if (isOption && !matchedRule) { + throw new Error("unrecognized option: " + arg); + } + } + if (seenNonOptionArg || !isOption) { + options["arguments"].push(arg); + } + } + return options; + }; + + OptionParser.prototype.help = function() { + var letPart, lines, rule, spaces, _i, _len, _ref; + lines = []; + if (this.banner) { + lines.unshift("" + this.banner + "\n"); + } + _ref = this.rules; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + spaces = 15 - rule.longFlag.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; + lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); + } + return "\n" + (lines.join('\n')) + "\n"; + }; + + return OptionParser; + + })(); + + LONG_FLAG = /^(--\w[\w\-]*)/; + + SHORT_FLAG = /^(-\w)$/; + + MULTI_FLAG = /^-(\w{2,})/; + + OPTIONAL = /\[(\w+(\*?))\]/; + + buildRules = function(rules) { + var tuple, _i, _len, _results; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + tuple = rules[_i]; + if (tuple.length < 3) { + tuple.unshift(null); + } + _results.push(buildRule.apply(null, tuple)); + } + return _results; + }; + + buildRule = function(shortFlag, longFlag, description, options) { + var match; + if (options == null) { + options = {}; + } + match = longFlag.match(OPTIONAL); + longFlag = longFlag.match(LONG_FLAG)[1]; + return { + name: longFlag.substr(2), + shortFlag: shortFlag, + longFlag: longFlag, + description: description, + hasArgument: !!(match && match[1]), + isList: !!(match && match[2]) + }; + }; + + normalizeArguments = function(args) { + var arg, l, match, result, _i, _j, _len, _len1, _ref; + args = args.slice(0); + result = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + if (match = arg.match(MULTI_FLAG)) { + _ref = match[1].split(''); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + l = _ref[_j]; + result.push('-' + l); + } + } else { + result.push(arg); + } + } + return result; + }; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/parser.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/parser.js new file mode 100755 index 000000000..f0499038e --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/parser.js @@ -0,0 +1,683 @@ +/* Jison generated parser */ +var parser = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"UNDEFINED":36,"NULL":37,"BOOL":38,"Assignable":39,"=":40,"AssignObj":41,"ObjAssignable":42,":":43,"ThisProperty":44,"RETURN":45,"HERECOMMENT":46,"PARAM_START":47,"ParamList":48,"PARAM_END":49,"FuncGlyph":50,"->":51,"=>":52,"OptComma":53,",":54,"Param":55,"ParamVar":56,"...":57,"Array":58,"Object":59,"Splat":60,"SimpleAssignable":61,"Accessor":62,"Parenthetical":63,"Range":64,"This":65,".":66,"?.":67,"::":68,"Index":69,"INDEX_START":70,"IndexValue":71,"INDEX_END":72,"INDEX_SOAK":73,"Slice":74,"{":75,"AssignList":76,"}":77,"CLASS":78,"EXTENDS":79,"OptFuncExist":80,"Arguments":81,"SUPER":82,"FUNC_EXIST":83,"CALL_START":84,"CALL_END":85,"ArgList":86,"THIS":87,"@":88,"[":89,"]":90,"RangeDots":91,"..":92,"Arg":93,"SimpleArgs":94,"TRY":95,"Catch":96,"FINALLY":97,"CATCH":98,"THROW":99,"(":100,")":101,"WhileSource":102,"WHILE":103,"WHEN":104,"UNTIL":105,"Loop":106,"LOOP":107,"ForBody":108,"FOR":109,"ForStart":110,"ForSource":111,"ForVariables":112,"OWN":113,"ForValue":114,"FORIN":115,"FOROF":116,"BY":117,"SWITCH":118,"Whens":119,"ELSE":120,"When":121,"LEADING_WHEN":122,"IfBlock":123,"IF":124,"POST_IF":125,"UNARY":126,"-":127,"+":128,"--":129,"++":130,"?":131,"MATH":132,"SHIFT":133,"COMPARE":134,"LOGIC":135,"RELATION":136,"COMPOUND_ASSIGN":137,"$accept":0,"$end":1}, +terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"}, +productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1:return this.$ = new yy.Block; +break; +case 2:return this.$ = $$[$0]; +break; +case 3:return this.$ = $$[$0-1]; +break; +case 4:this.$ = yy.Block.wrap([$$[$0]]); +break; +case 5:this.$ = $$[$0-2].push($$[$0]); +break; +case 6:this.$ = $$[$0-1]; +break; +case 7:this.$ = $$[$0]; +break; +case 8:this.$ = $$[$0]; +break; +case 9:this.$ = $$[$0]; +break; +case 10:this.$ = $$[$0]; +break; +case 11:this.$ = new yy.Literal($$[$0]); +break; +case 12:this.$ = $$[$0]; +break; +case 13:this.$ = $$[$0]; +break; +case 14:this.$ = $$[$0]; +break; +case 15:this.$ = $$[$0]; +break; +case 16:this.$ = $$[$0]; +break; +case 17:this.$ = $$[$0]; +break; +case 18:this.$ = $$[$0]; +break; +case 19:this.$ = $$[$0]; +break; +case 20:this.$ = $$[$0]; +break; +case 21:this.$ = $$[$0]; +break; +case 22:this.$ = $$[$0]; +break; +case 23:this.$ = $$[$0]; +break; +case 24:this.$ = new yy.Block; +break; +case 25:this.$ = $$[$0-1]; +break; +case 26:this.$ = new yy.Literal($$[$0]); +break; +case 27:this.$ = new yy.Literal($$[$0]); +break; +case 28:this.$ = new yy.Literal($$[$0]); +break; +case 29:this.$ = $$[$0]; +break; +case 30:this.$ = new yy.Literal($$[$0]); +break; +case 31:this.$ = new yy.Literal($$[$0]); +break; +case 32:this.$ = new yy.Literal($$[$0]); +break; +case 33:this.$ = new yy.Undefined; +break; +case 34:this.$ = new yy.Null; +break; +case 35:this.$ = new yy.Bool($$[$0]); +break; +case 36:this.$ = new yy.Assign($$[$0-2], $$[$0]); +break; +case 37:this.$ = new yy.Assign($$[$0-3], $$[$0]); +break; +case 38:this.$ = new yy.Assign($$[$0-4], $$[$0-1]); +break; +case 39:this.$ = new yy.Value($$[$0]); +break; +case 40:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object'); +break; +case 41:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object'); +break; +case 42:this.$ = $$[$0]; +break; +case 43:this.$ = $$[$0]; +break; +case 44:this.$ = $$[$0]; +break; +case 45:this.$ = $$[$0]; +break; +case 46:this.$ = new yy.Return($$[$0]); +break; +case 47:this.$ = new yy.Return; +break; +case 48:this.$ = new yy.Comment($$[$0]); +break; +case 49:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]); +break; +case 50:this.$ = new yy.Code([], $$[$0], $$[$0-1]); +break; +case 51:this.$ = 'func'; +break; +case 52:this.$ = 'boundfunc'; +break; +case 53:this.$ = $$[$0]; +break; +case 54:this.$ = $$[$0]; +break; +case 55:this.$ = []; +break; +case 56:this.$ = [$$[$0]]; +break; +case 57:this.$ = $$[$0-2].concat($$[$0]); +break; +case 58:this.$ = $$[$0-3].concat($$[$0]); +break; +case 59:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 60:this.$ = new yy.Param($$[$0]); +break; +case 61:this.$ = new yy.Param($$[$0-1], null, true); +break; +case 62:this.$ = new yy.Param($$[$0-2], $$[$0]); +break; +case 63:this.$ = $$[$0]; +break; +case 64:this.$ = $$[$0]; +break; +case 65:this.$ = $$[$0]; +break; +case 66:this.$ = $$[$0]; +break; +case 67:this.$ = new yy.Splat($$[$0-1]); +break; +case 68:this.$ = new yy.Value($$[$0]); +break; +case 69:this.$ = $$[$0-1].add($$[$0]); +break; +case 70:this.$ = new yy.Value($$[$0-1], [].concat($$[$0])); +break; +case 71:this.$ = $$[$0]; +break; +case 72:this.$ = $$[$0]; +break; +case 73:this.$ = new yy.Value($$[$0]); +break; +case 74:this.$ = new yy.Value($$[$0]); +break; +case 75:this.$ = $$[$0]; +break; +case 76:this.$ = new yy.Value($$[$0]); +break; +case 77:this.$ = new yy.Value($$[$0]); +break; +case 78:this.$ = new yy.Value($$[$0]); +break; +case 79:this.$ = $$[$0]; +break; +case 80:this.$ = new yy.Access($$[$0]); +break; +case 81:this.$ = new yy.Access($$[$0], 'soak'); +break; +case 82:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])]; +break; +case 83:this.$ = new yy.Access(new yy.Literal('prototype')); +break; +case 84:this.$ = $$[$0]; +break; +case 85:this.$ = $$[$0-1]; +break; +case 86:this.$ = yy.extend($$[$0], { + soak: true + }); +break; +case 87:this.$ = new yy.Index($$[$0]); +break; +case 88:this.$ = new yy.Slice($$[$0]); +break; +case 89:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated); +break; +case 90:this.$ = []; +break; +case 91:this.$ = [$$[$0]]; +break; +case 92:this.$ = $$[$0-2].concat($$[$0]); +break; +case 93:this.$ = $$[$0-3].concat($$[$0]); +break; +case 94:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 95:this.$ = new yy.Class; +break; +case 96:this.$ = new yy.Class(null, null, $$[$0]); +break; +case 97:this.$ = new yy.Class(null, $$[$0]); +break; +case 98:this.$ = new yy.Class(null, $$[$0-1], $$[$0]); +break; +case 99:this.$ = new yy.Class($$[$0]); +break; +case 100:this.$ = new yy.Class($$[$0-1], null, $$[$0]); +break; +case 101:this.$ = new yy.Class($$[$0-2], $$[$0]); +break; +case 102:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]); +break; +case 103:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 104:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 105:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]); +break; +case 106:this.$ = new yy.Call('super', $$[$0]); +break; +case 107:this.$ = false; +break; +case 108:this.$ = true; +break; +case 109:this.$ = []; +break; +case 110:this.$ = $$[$0-2]; +break; +case 111:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 112:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 113:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this'); +break; +case 114:this.$ = new yy.Arr([]); +break; +case 115:this.$ = new yy.Arr($$[$0-2]); +break; +case 116:this.$ = 'inclusive'; +break; +case 117:this.$ = 'exclusive'; +break; +case 118:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]); +break; +case 119:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]); +break; +case 120:this.$ = new yy.Range($$[$0-1], null, $$[$0]); +break; +case 121:this.$ = new yy.Range(null, $$[$0], $$[$0-1]); +break; +case 122:this.$ = new yy.Range(null, null, $$[$0]); +break; +case 123:this.$ = [$$[$0]]; +break; +case 124:this.$ = $$[$0-2].concat($$[$0]); +break; +case 125:this.$ = $$[$0-3].concat($$[$0]); +break; +case 126:this.$ = $$[$0-2]; +break; +case 127:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 128:this.$ = $$[$0]; +break; +case 129:this.$ = $$[$0]; +break; +case 130:this.$ = $$[$0]; +break; +case 131:this.$ = [].concat($$[$0-2], $$[$0]); +break; +case 132:this.$ = new yy.Try($$[$0]); +break; +case 133:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]); +break; +case 134:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]); +break; +case 135:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]); +break; +case 136:this.$ = [$$[$0-1], $$[$0]]; +break; +case 137:this.$ = new yy.Throw($$[$0]); +break; +case 138:this.$ = new yy.Parens($$[$0-1]); +break; +case 139:this.$ = new yy.Parens($$[$0-2]); +break; +case 140:this.$ = new yy.While($$[$0]); +break; +case 141:this.$ = new yy.While($$[$0-2], { + guard: $$[$0] + }); +break; +case 142:this.$ = new yy.While($$[$0], { + invert: true + }); +break; +case 143:this.$ = new yy.While($$[$0-2], { + invert: true, + guard: $$[$0] + }); +break; +case 144:this.$ = $$[$0-1].addBody($$[$0]); +break; +case 145:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 146:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 147:this.$ = $$[$0]; +break; +case 148:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]); +break; +case 149:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]])); +break; +case 150:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 151:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 152:this.$ = new yy.For($$[$0], $$[$0-1]); +break; +case 153:this.$ = { + source: new yy.Value($$[$0]) + }; +break; +case 154:this.$ = (function () { + $$[$0].own = $$[$0-1].own; + $$[$0].name = $$[$0-1][0]; + $$[$0].index = $$[$0-1][1]; + return $$[$0]; + }()); +break; +case 155:this.$ = $$[$0]; +break; +case 156:this.$ = (function () { + $$[$0].own = true; + return $$[$0]; + }()); +break; +case 157:this.$ = $$[$0]; +break; +case 158:this.$ = $$[$0]; +break; +case 159:this.$ = new yy.Value($$[$0]); +break; +case 160:this.$ = new yy.Value($$[$0]); +break; +case 161:this.$ = [$$[$0]]; +break; +case 162:this.$ = [$$[$0-2], $$[$0]]; +break; +case 163:this.$ = { + source: $$[$0] + }; +break; +case 164:this.$ = { + source: $$[$0], + object: true + }; +break; +case 165:this.$ = { + source: $$[$0-2], + guard: $$[$0] + }; +break; +case 166:this.$ = { + source: $$[$0-2], + guard: $$[$0], + object: true + }; +break; +case 167:this.$ = { + source: $$[$0-2], + step: $$[$0] + }; +break; +case 168:this.$ = { + source: $$[$0-4], + guard: $$[$0-2], + step: $$[$0] + }; +break; +case 169:this.$ = { + source: $$[$0-4], + step: $$[$0-2], + guard: $$[$0] + }; +break; +case 170:this.$ = new yy.Switch($$[$0-3], $$[$0-1]); +break; +case 171:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]); +break; +case 172:this.$ = new yy.Switch(null, $$[$0-1]); +break; +case 173:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]); +break; +case 174:this.$ = $$[$0]; +break; +case 175:this.$ = $$[$0-1].concat($$[$0]); +break; +case 176:this.$ = [[$$[$0-1], $$[$0]]]; +break; +case 177:this.$ = [[$$[$0-2], $$[$0-1]]]; +break; +case 178:this.$ = new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + }); +break; +case 179:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + })); +break; +case 180:this.$ = $$[$0]; +break; +case 181:this.$ = $$[$0-2].addElse($$[$0]); +break; +case 182:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 183:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 184:this.$ = new yy.Op($$[$0-1], $$[$0]); +break; +case 185:this.$ = new yy.Op('-', $$[$0]); +break; +case 186:this.$ = new yy.Op('+', $$[$0]); +break; +case 187:this.$ = new yy.Op('--', $$[$0]); +break; +case 188:this.$ = new yy.Op('++', $$[$0]); +break; +case 189:this.$ = new yy.Op('--', $$[$0-1], null, true); +break; +case 190:this.$ = new yy.Op('++', $$[$0-1], null, true); +break; +case 191:this.$ = new yy.Existence($$[$0-1]); +break; +case 192:this.$ = new yy.Op('+', $$[$0-2], $$[$0]); +break; +case 193:this.$ = new yy.Op('-', $$[$0-2], $$[$0]); +break; +case 194:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 195:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 196:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 197:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 198:this.$ = (function () { + if ($$[$0-1].charAt(0) === '!') { + return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); + } else { + return new yy.Op($$[$0-1], $$[$0-2], $$[$0]); + } + }()); +break; +case 199:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]); +break; +case 200:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]); +break; +case 201:this.$ = new yy.Extends($$[$0-2], $$[$0]); +break; +} +}, +table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}], +defaultActions: {60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}}; +undefined +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = parser; +exports.parse = function () { return parser.parse.apply(parser, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + if (typeof process !== 'undefined') { + var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); + } else { + var cwd = require("file").path(require("file").cwd()); + var source = cwd.join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +} \ No newline at end of file diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/repl.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/repl.js new file mode 100644 index 000000000..b4a4765d3 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/repl.js @@ -0,0 +1,261 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, REPL_PROMPT_MULTILINE, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, multilineMode, pipedInput, readline, repl, run, stdin, stdout; + + stdin = process.openStdin(); + + stdout = process.stdout; + + CoffeeScript = require('./coffee-script'); + + readline = require('readline'); + + inspect = require('util').inspect; + + Script = require('vm').Script; + + Module = require('module'); + + REPL_PROMPT = 'coffee> '; + + REPL_PROMPT_MULTILINE = '------> '; + + REPL_PROMPT_CONTINUATION = '......> '; + + enableColours = false; + + if (process.platform !== 'win32') { + enableColours = !process.env.NODE_DISABLE_COLORS; + } + + error = function(err) { + return stdout.write((err.stack || err.toString()) + '\n'); + }; + + ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/; + + SIMPLEVAR = /(\w+)$/i; + + autocomplete = function(text) { + return completeAttribute(text) || completeVariable(text) || [[], text]; + }; + + completeAttribute = function(text) { + var all, completions, key, match, obj, possibilities, prefix, val; + if (match = text.match(ACCESSOR)) { + all = match[0], obj = match[1], prefix = match[2]; + try { + val = Script.runInThisContext(obj); + } catch (error) { + return; + } + val = Object(val); + possibilities = Object.getOwnPropertyNames(val); + for (key in val) { + if (~possibilities.indexOf(val)) { + possibilities.push(key); + } + } + completions = getCompletions(prefix, possibilities); + return [completions, prefix]; + } + }; + + completeVariable = function(text) { + var completions, free, keywords, possibilities, r, vars, _ref; + free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0; + if (text === "") { + free = ""; + } + if (free != null) { + vars = Script.runInThisContext('Object.getOwnPropertyNames(Object(this))'); + keywords = (function() { + var _i, _len, _ref1, _results; + _ref1 = CoffeeScript.RESERVED; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + r = _ref1[_i]; + if (r.slice(0, 2) !== '__') { + _results.push(r); + } + } + return _results; + })(); + possibilities = vars.concat(keywords); + completions = getCompletions(free, possibilities); + return [completions, free]; + } + }; + + getCompletions = function(prefix, candidates) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + el = candidates[_i]; + if (el.indexOf(prefix) === 0) { + _results.push(el); + } + } + return _results; + }; + + process.on('uncaughtException', error); + + backlog = ''; + + run = function(buffer) { + var code, returnValue, _; + buffer = buffer.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3"); + buffer = buffer.replace(/[\r\n]+$/, ""); + if (multilineMode) { + backlog += "" + buffer + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + if (!buffer.toString().trim() && !backlog) { + repl.prompt(); + return; + } + code = backlog += buffer; + if (code[code.length - 1] === '\\') { + backlog = "" + backlog.slice(0, -1) + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + repl.setPrompt(REPL_PROMPT); + backlog = ''; + try { + _ = global._; + returnValue = CoffeeScript["eval"]("_=(" + code + "\n)", { + filename: 'repl', + modulename: 'repl' + }); + if (returnValue === void 0) { + global._ = _; + } + repl.output.write("" + (inspect(returnValue, false, 2, enableColours)) + "\n"); + } catch (err) { + error(err); + } + return repl.prompt(); + }; + + if (stdin.readable) { + pipedInput = ''; + repl = { + prompt: function() { + return stdout.write(this._prompt); + }, + setPrompt: function(p) { + return this._prompt = p; + }, + input: stdin, + output: stdout, + on: function() {} + }; + stdin.on('data', function(chunk) { + var line, lines, _i, _len, _ref; + pipedInput += chunk; + if (!/\n/.test(pipedInput)) { + return; + } + lines = pipedInput.split("\n"); + pipedInput = lines[lines.length - 1]; + _ref = lines.slice(0, -1); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + }); + stdin.on('end', function() { + var line, _i, _len, _ref; + _ref = pipedInput.trim().split("\n"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + stdout.write('\n'); + return process.exit(0); + }); + } else { + if (readline.createInterface.length < 3) { + repl = readline.createInterface(stdin, autocomplete); + stdin.on('data', function(buffer) { + return repl.write(buffer); + }); + } else { + repl = readline.createInterface(stdin, stdout, autocomplete); + } + } + + multilineMode = false; + + repl.input.on('keypress', function(char, key) { + var cursorPos, newPrompt; + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) { + return; + } + cursorPos = repl.cursor; + repl.output.cursorTo(0); + repl.output.clearLine(1); + multilineMode = !multilineMode; + if (!multilineMode && backlog) { + repl._line(); + } + backlog = ''; + repl.setPrompt((newPrompt = multilineMode ? REPL_PROMPT_MULTILINE : REPL_PROMPT)); + repl.prompt(); + return repl.output.cursorTo(newPrompt.length + (repl.cursor = cursorPos)); + }); + + repl.input.on('keypress', function(char, key) { + if (!(multilineMode && repl.line)) { + return; + } + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'd')) { + return; + } + multilineMode = false; + return repl._line(); + }); + + repl.on('attemptClose', function() { + if (multilineMode) { + multilineMode = false; + repl.output.cursorTo(0); + repl.output.clearLine(1); + repl._onLine(repl.line); + return; + } + if (backlog) { + backlog = ''; + repl.output.write('\n'); + repl.setPrompt(REPL_PROMPT); + return repl.prompt(); + } else { + return repl.close(); + } + }); + + repl.on('close', function() { + repl.output.write('\n'); + return repl.input.destroy(); + }); + + repl.on('line', run); + + repl.setPrompt(REPL_PROMPT); + + repl.prompt(); + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/rewriter.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/rewriter.js new file mode 100644 index 000000000..d26133ca7 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/rewriter.js @@ -0,0 +1,349 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __slice = [].slice; + + exports.Rewriter = (function() { + + function Rewriter() {} + + Rewriter.prototype.rewrite = function(tokens) { + this.tokens = tokens; + this.removeLeadingNewlines(); + this.removeMidExpressionNewlines(); + this.closeOpenCalls(); + this.closeOpenIndexes(); + this.addImplicitIndentation(); + this.tagPostfixConditionals(); + this.addImplicitBraces(); + this.addImplicitParentheses(); + return this.tokens; + }; + + Rewriter.prototype.scanTokens = function(block) { + var i, token, tokens; + tokens = this.tokens; + i = 0; + while (token = tokens[i]) { + i += block.call(this, token, i, tokens); + } + return true; + }; + + Rewriter.prototype.detectEnd = function(i, condition, action) { + var levels, token, tokens, _ref, _ref1; + tokens = this.tokens; + levels = 0; + while (token = tokens[i]) { + if (levels === 0 && condition.call(this, token, i)) { + return action.call(this, token, i); + } + if (!token || levels < 0) { + return action.call(this, token, i - 1); + } + if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) { + levels += 1; + } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) { + levels -= 1; + } + i += 1; + } + return i - 1; + }; + + Rewriter.prototype.removeLeadingNewlines = function() { + var i, tag, _i, _len, _ref; + _ref = this.tokens; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + tag = _ref[i][0]; + if (tag !== 'TERMINATOR') { + break; + } + } + if (i) { + return this.tokens.splice(0, i); + } + }; + + Rewriter.prototype.removeMidExpressionNewlines = function() { + return this.scanTokens(function(token, i, tokens) { + var _ref; + if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) { + return 1; + } + tokens.splice(i, 1); + return 0; + }); + }; + + Rewriter.prototype.closeOpenCalls = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')'; + }; + action = function(token, i) { + return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'CALL_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.closeOpenIndexes = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === ']' || _ref === 'INDEX_END'; + }; + action = function(token, i) { + return token[0] = 'INDEX_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'INDEX_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.addImplicitBraces = function() { + var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine; + stack = []; + start = null; + startsLine = null; + sameLine = true; + startIndent = 0; + startIndex = 0; + condition = function(token, i) { + var one, tag, three, two, _ref, _ref1; + _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2]; + if ('HERECOMMENT' === (one != null ? one[0] : void 0)) { + return false; + } + tag = token[0]; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + sameLine = false; + } + return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT')); + }; + action = function(token, i) { + var tok; + tok = this.generate('}', '}', token[2]); + return this.tokens.splice(i, 0, tok); + }; + return this.scanTokens(function(token, i, tokens) { + var ago, idx, prevTag, tag, tok, value, _ref, _ref1; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { + stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]); + return 1; + } + if (__indexOf.call(EXPRESSION_END, tag) >= 0) { + start = stack.pop(); + return 1; + } + if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) { + return 1; + } + sameLine = true; + startIndex = i + 1; + stack.push(['{']); + idx = ago === '@' ? i - 2 : i - 1; + while (this.tag(idx - 2) === 'HERECOMMENT') { + idx -= 2; + } + prevTag = this.tag(idx - 1); + startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0); + value = new String('{'); + value.generated = true; + tok = this.generate('{', value, token[2]); + tokens.splice(idx, 0, tok); + this.detectEnd(i + 2, condition, action); + return 2; + }); + }; + + Rewriter.prototype.addImplicitParentheses = function() { + var action, condition, noCall, seenControl, seenSingle; + noCall = seenSingle = seenControl = false; + condition = function(token, i) { + var post, tag, _ref, _ref1; + tag = token[0]; + if (!seenSingle && token.fromThen) { + return true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') { + seenSingle = true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') { + seenControl = true; + } + if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') { + return true; + } + return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{'))); + }; + action = function(token, i) { + return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2])); + }; + return this.scanTokens(function(token, i, tokens) { + var callObject, current, next, prev, tag, _ref, _ref1, _ref2; + tag = token[0]; + if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') { + noCall = true; + } + _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2]; + callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0); + seenSingle = false; + seenControl = false; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + noCall = false; + } + if (prev && !prev.spaced && tag === '?') { + token.call = true; + } + if (token.fromThen) { + return 1; + } + if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) { + return 1; + } + tokens.splice(i, 0, this.generate('CALL_START', '(', token[2])); + this.detectEnd(i + 1, condition, action); + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + return 2; + }); + }; + + Rewriter.prototype.addImplicitIndentation = function() { + var action, condition, indent, outdent, starter; + starter = indent = outdent = null; + condition = function(token, i) { + var _ref; + return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN')); + }; + action = function(token, i) { + return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent); + }; + return this.scanTokens(function(token, i, tokens) { + var tag, _ref, _ref1; + tag = token[0]; + if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') { + tokens.splice(i, 1); + return 0; + } + if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { + tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token)))); + return 2; + } + if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) { + tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token)))); + return 4; + } + if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { + starter = tag; + _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1]; + if (starter === 'THEN') { + indent.fromThen = true; + } + tokens.splice(i + 1, 0, indent); + this.detectEnd(i + 2, condition, action); + if (tag === 'THEN') { + tokens.splice(i, 1); + } + return 1; + } + return 1; + }); + }; + + Rewriter.prototype.tagPostfixConditionals = function() { + var action, condition, original; + original = null; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT'; + }; + action = function(token, i) { + if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) { + return original[0] = 'POST_' + original[0]; + } + }; + return this.scanTokens(function(token, i) { + if (token[0] !== 'IF') { + return 1; + } + original = token; + this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.indentation = function(token, implicit) { + var indent, outdent; + if (implicit == null) { + implicit = false; + } + indent = ['INDENT', 2, token[2]]; + outdent = ['OUTDENT', 2, token[2]]; + if (implicit) { + indent.generated = outdent.generated = true; + } + return [indent, outdent]; + }; + + Rewriter.prototype.generate = function(tag, value, line) { + var tok; + tok = [tag, value, line]; + tok.generated = true; + return tok; + }; + + Rewriter.prototype.tag = function(i) { + var _ref; + return (_ref = this.tokens[i]) != null ? _ref[0] : void 0; + }; + + return Rewriter; + + })(); + + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']]; + + exports.INVERSES = INVERSES = {}; + + EXPRESSION_START = []; + + EXPRESSION_END = []; + + for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) { + _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1]; + EXPRESSION_START.push(INVERSES[rite] = left); + EXPRESSION_END.push(INVERSES[left] = rite); + } + + EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); + + IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; + + IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++']; + + IMPLICIT_UNSPACED_CALL = ['+', '-']; + + IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']; + + IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']; + + SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']; + + SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']; + + LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/scope.js b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/scope.js new file mode 100644 index 000000000..3efc4ede6 --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/lib/coffee-script/scope.js @@ -0,0 +1,146 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Scope, extend, last, _ref; + + _ref = require('./helpers'), extend = _ref.extend, last = _ref.last; + + exports.Scope = Scope = (function() { + + Scope.root = null; + + function Scope(parent, expressions, method) { + this.parent = parent; + this.expressions = expressions; + this.method = method; + this.variables = [ + { + name: 'arguments', + type: 'arguments' + } + ]; + this.positions = {}; + if (!this.parent) { + Scope.root = this; + } + } + + Scope.prototype.add = function(name, type, immediate) { + if (this.shared && !immediate) { + return this.parent.add(name, type, immediate); + } + if (Object.prototype.hasOwnProperty.call(this.positions, name)) { + return this.variables[this.positions[name]].type = type; + } else { + return this.positions[name] = this.variables.push({ + name: name, + type: type + }) - 1; + } + }; + + Scope.prototype.namedMethod = function() { + if (this.method.name || !this.parent) { + return this.method; + } + return this.parent.namedMethod(); + }; + + Scope.prototype.find = function(name) { + if (this.check(name)) { + return true; + } + this.add(name, 'var'); + return false; + }; + + Scope.prototype.parameter = function(name) { + if (this.shared && this.parent.check(name, true)) { + return; + } + return this.add(name, 'param'); + }; + + Scope.prototype.check = function(name) { + var _ref1; + return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0)); + }; + + Scope.prototype.temporary = function(name, index) { + if (name.length > 1) { + return '_' + name + (index > 1 ? index - 1 : ''); + } else { + return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); + } + }; + + Scope.prototype.type = function(name) { + var v, _i, _len, _ref1; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.name === name) { + return v.type; + } + } + return null; + }; + + Scope.prototype.freeVariable = function(name, reserve) { + var index, temp; + if (reserve == null) { + reserve = true; + } + index = 0; + while (this.check((temp = this.temporary(name, index)))) { + index++; + } + if (reserve) { + this.add(temp, 'var', true); + } + return temp; + }; + + Scope.prototype.assign = function(name, value) { + this.add(name, { + value: value, + assigned: true + }, true); + return this.hasAssignments = true; + }; + + Scope.prototype.hasDeclarations = function() { + return !!this.declaredVariables().length; + }; + + Scope.prototype.declaredVariables = function() { + var realVars, tempVars, v, _i, _len, _ref1; + realVars = []; + tempVars = []; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type === 'var') { + (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name); + } + } + return realVars.sort().concat(tempVars.sort()); + }; + + Scope.prototype.assignedVariables = function() { + var v, _i, _len, _ref1, _results; + _ref1 = this.variables; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type.assigned) { + _results.push("" + v.name + " = " + v.type.value); + } + } + return _results; + }; + + return Scope; + + })(); + +}).call(this); diff --git a/node_modules/grunt/node_modules/coffee-script/package.json b/node_modules/grunt/node_modules/coffee-script/package.json new file mode 100644 index 000000000..d2583c14c --- /dev/null +++ b/node_modules/grunt/node_modules/coffee-script/package.json @@ -0,0 +1,51 @@ +{ + "name": "coffee-script", + "description": "Unfancy JavaScript", + "keywords": [ + "javascript", + "language", + "coffeescript", + "compiler" + ], + "author": { + "name": "Jeremy Ashkenas" + }, + "version": "1.3.3", + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE" + } + ], + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "lib": "./lib/coffee-script" + }, + "main": "./lib/coffee-script/coffee-script", + "bin": { + "coffee": "./bin/coffee", + "cake": "./bin/cake" + }, + "homepage": "http://coffeescript.org", + "bugs": { + "url": "https://github.com/jashkenas/coffee-script/issues" + }, + "repository": { + "type": "git", + "url": "git://github.com/jashkenas/coffee-script.git" + }, + "devDependencies": { + "uglify-js": ">=1.0.0", + "jison": ">=0.2.0" + }, + "readme": "\n {\n } } {\n { { } }\n } }{ {\n { }{ } } _____ __ __\n ( }{ }{ { ) / ____| / _|/ _|\n .- { { } { }} -. | | ___ | |_| |_ ___ ___\n ( ( } { } { } } ) | | / _ \\| _| _/ _ \\/ _ \\\n |`-..________ ..-'| | |___| (_) | | | || __/ __/\n | | \\_____\\___/|_| |_| \\___|\\___|\n | ;--.\n | (__ \\ _____ _ _\n | | ) ) / ____| (_) | |\n | |/ / | (___ ___ _ __ _ _ __ | |_\n | ( / \\___ \\ / __| '__| | '_ \\| __|\n | |/ ____) | (__| | | | |_) | |_\n | | |_____/ \\___|_| |_| .__/ \\__|\n `-.._________..-' | |\n |_|\n\n\n CoffeeScript is a little language that compiles into JavaScript.\n\n Install Node.js, and then the CoffeeScript compiler:\n sudo bin/cake install\n\n Or, if you have the Node Package Manager installed:\n npm install -g coffee-script\n (Leave off the -g if you don't wish to install globally.)\n\n Execute a script:\n coffee /path/to/script.coffee\n\n Compile a script:\n coffee -c /path/to/script.coffee\n\n For documentation, usage, and examples, see:\n http://coffeescript.org/\n\n To suggest a feature, report a bug, or general discussion:\n http://github.com/jashkenas/coffee-script/issues/\n\n If you'd like to chat, drop by #coffeescript on Freenode IRC,\n or on webchat.freenode.net.\n\n The source repository:\n git://github.com/jashkenas/coffee-script.git\n\n All contributors are listed here:\n http://github.com/jashkenas/coffee-script/contributors\n", + "readmeFilename": "README", + "_id": "coffee-script@1.3.3", + "dist": { + "shasum": "b602e2a00e2795959216b993a926e9d39c5882ab" + }, + "_from": "coffee-script@~1.3.3", + "_resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz" +} diff --git a/node_modules/grunt/node_modules/colors/MIT-LICENSE.txt b/node_modules/grunt/node_modules/colors/MIT-LICENSE.txt new file mode 100644 index 000000000..7dca10706 --- /dev/null +++ b/node_modules/grunt/node_modules/colors/MIT-LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt/node_modules/colors/ReadMe.md b/node_modules/grunt/node_modules/colors/ReadMe.md new file mode 100644 index 000000000..0eda52db2 --- /dev/null +++ b/node_modules/grunt/node_modules/colors/ReadMe.md @@ -0,0 +1,77 @@ +# colors.js - get color and style in your node.js console ( and browser ) like what + + + + +## Installation + + npm install colors + +## colors and styles! + +- bold +- italic +- underline +- inverse +- yellow +- cyan +- white +- magenta +- green +- red +- grey +- blue +- rainbow +- zebra +- random + +## Usage + +``` js +var colors = require('./colors'); + +console.log('hello'.green); // outputs green text +console.log('i like cake and pies'.underline.red) // outputs red underlined text +console.log('inverse the color'.inverse); // inverses the color +console.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces) +``` + +# Creating Custom themes + +```js + +var colors = require('colors'); + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); +``` + + +### Contributors + +Marak (Marak Squires) +Alexis Sellier (cloudhead) +mmalecki (Maciej Małecki) +nicoreed (Nico Reed) +morganrallen (Morgan Allen) +JustinCampbell (Justin Campbell) +ded (Dustin Diaz) + + +#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded) diff --git a/node_modules/grunt/node_modules/colors/colors.js b/node_modules/grunt/node_modules/colors/colors.js new file mode 100644 index 000000000..7a537d8de --- /dev/null +++ b/node_modules/grunt/node_modules/colors/colors.js @@ -0,0 +1,342 @@ +/* +colors.js + +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +var isHeadless = false; + +if (typeof module !== 'undefined') { + isHeadless = true; +} + +if (!isHeadless) { + var exports = {}; + var module = {}; + var colors = exports; + exports.mode = "browser"; +} else { + exports.mode = "console"; +} + +// +// Prototypes the string object to have additional method calls that add terminal colors +// +var addProperty = function (color, func) { + exports[color] = function (str) { + return func.apply(str); + }; + String.prototype.__defineGetter__(color, func); +}; + +function stylize(str, style) { + + var styles; + + if (exports.mode === 'console') { + styles = { + //styles + 'bold' : ['\x1B[1m', '\x1B[22m'], + 'italic' : ['\x1B[3m', '\x1B[23m'], + 'underline' : ['\x1B[4m', '\x1B[24m'], + 'inverse' : ['\x1B[7m', '\x1B[27m'], + 'strikethrough' : ['\x1B[9m', '\x1B[29m'], + //text colors + //grayscale + 'white' : ['\x1B[37m', '\x1B[39m'], + 'grey' : ['\x1B[90m', '\x1B[39m'], + 'black' : ['\x1B[30m', '\x1B[39m'], + //colors + 'blue' : ['\x1B[34m', '\x1B[39m'], + 'cyan' : ['\x1B[36m', '\x1B[39m'], + 'green' : ['\x1B[32m', '\x1B[39m'], + 'magenta' : ['\x1B[35m', '\x1B[39m'], + 'red' : ['\x1B[31m', '\x1B[39m'], + 'yellow' : ['\x1B[33m', '\x1B[39m'], + //background colors + //grayscale + 'whiteBG' : ['\x1B[47m', '\x1B[49m'], + 'greyBG' : ['\x1B[49;5;8m', '\x1B[49m'], + 'blackBG' : ['\x1B[40m', '\x1B[49m'], + //colors + 'blueBG' : ['\x1B[44m', '\x1B[49m'], + 'cyanBG' : ['\x1B[46m', '\x1B[49m'], + 'greenBG' : ['\x1B[42m', '\x1B[49m'], + 'magentaBG' : ['\x1B[45m', '\x1B[49m'], + 'redBG' : ['\x1B[41m', '\x1B[49m'], + 'yellowBG' : ['\x1B[43m', '\x1B[49m'] + }; + } else if (exports.mode === 'browser') { + styles = { + //styles + 'bold' : ['', ''], + 'italic' : ['', ''], + 'underline' : ['', ''], + 'inverse' : ['', ''], + 'strikethrough' : ['', ''], + //text colors + //grayscale + 'white' : ['', ''], + 'grey' : ['', ''], + 'black' : ['', ''], + //colors + 'blue' : ['', ''], + 'cyan' : ['', ''], + 'green' : ['', ''], + 'magenta' : ['', ''], + 'red' : ['', ''], + 'yellow' : ['', ''], + //background colors + //grayscale + 'whiteBG' : ['', ''], + 'greyBG' : ['', ''], + 'blackBG' : ['', ''], + //colors + 'blueBG' : ['', ''], + 'cyanBG' : ['', ''], + 'greenBG' : ['', ''], + 'magentaBG' : ['', ''], + 'redBG' : ['', ''], + 'yellowBG' : ['', ''] + }; + } else if (exports.mode === 'none') { + return str + ''; + } else { + console.log('unsupported mode, try "browser", "console" or "none"'); + } + return styles[style][0] + str + styles[style][1]; +} + +function applyTheme(theme) { + + // + // Remark: This is a list of methods that exist + // on String that you should not overwrite. + // + var stringPrototypeBlacklist = [ + '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', + 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', + 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', + 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' + ]; + + Object.keys(theme).forEach(function (prop) { + if (stringPrototypeBlacklist.indexOf(prop) !== -1) { + console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); + } + else { + if (typeof(theme[prop]) === 'string') { + addProperty(prop, function () { + return exports[theme[prop]](this); + }); + } + else { + addProperty(prop, function () { + var ret = this; + for (var t = 0; t < theme[prop].length; t++) { + ret = exports[theme[prop][t]](ret); + } + return ret; + }); + } + } + }); +} + + +// +// Iterate through all default styles and colors +// +var x = ['bold', 'underline', 'strikethrough', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta', 'greyBG', 'blackBG', 'yellowBG', 'redBG', 'greenBG', 'blueBG', 'whiteBG', 'cyanBG', 'magentaBG']; +x.forEach(function (style) { + + // __defineGetter__ at the least works in more browsers + // http://robertnyman.com/javascript/javascript-getters-setters.html + // Object.defineProperty only works in Chrome + addProperty(style, function () { + return stylize(this, style); + }); +}); + +function sequencer(map) { + return function () { + if (!isHeadless) { + return this.replace(/( )/, '$1'); + } + var exploded = this.split(""), i = 0; + exploded = exploded.map(map); + return exploded.join(""); + }; +} + +var rainbowMap = (function () { + var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV + return function (letter, i, exploded) { + if (letter === " ") { + return letter; + } else { + return stylize(letter, rainbowColors[i++ % rainbowColors.length]); + } + }; +})(); + +exports.themes = {}; + +exports.addSequencer = function (name, map) { + addProperty(name, sequencer(map)); +}; + +exports.addSequencer('rainbow', rainbowMap); +exports.addSequencer('zebra', function (letter, i, exploded) { + return i % 2 === 0 ? letter : letter.inverse; +}); + +exports.setTheme = function (theme) { + if (typeof theme === 'string') { + try { + exports.themes[theme] = require(theme); + applyTheme(exports.themes[theme]); + return exports.themes[theme]; + } catch (err) { + console.log(err); + return err; + } + } else { + applyTheme(theme); + } +}; + + +addProperty('stripColors', function () { + return ("" + this).replace(/\x1B\[\d+m/g, ''); +}); + +// please no +function zalgo(text, options) { + var soul = { + "up" : [ + '̍', '̎', '̄', '̅', + '̿', '̑', '̆', '̐', + '͒', '͗', '͑', '̇', + '̈', '̊', '͂', '̓', + '̈', '͊', '͋', '͌', + '̃', '̂', '̌', '͐', + '̀', '́', '̋', '̏', + '̒', '̓', '̔', '̽', + '̉', 'ͣ', 'ͤ', 'ͥ', + 'ͦ', 'ͧ', 'ͨ', 'ͩ', + 'ͪ', 'ͫ', 'ͬ', 'ͭ', + 'ͮ', 'ͯ', '̾', '͛', + '͆', '̚' + ], + "down" : [ + '̖', '̗', '̘', '̙', + '̜', '̝', '̞', '̟', + '̠', '̤', '̥', '̦', + '̩', '̪', '̫', '̬', + '̭', '̮', '̯', '̰', + '̱', '̲', '̳', '̹', + '̺', '̻', '̼', 'ͅ', + '͇', '͈', '͉', '͍', + '͎', '͓', '͔', '͕', + '͖', '͙', '͚', '̣' + ], + "mid" : [ + '̕', '̛', '̀', '́', + '͘', '̡', '̢', '̧', + '̨', '̴', '̵', '̶', + '͜', '͝', '͞', + '͟', '͠', '͢', '̸', + '̷', '͡', ' ҉' + ] + }, + all = [].concat(soul.up, soul.down, soul.mid), + zalgo = {}; + + function randomNumber(range) { + var r = Math.floor(Math.random() * range); + return r; + } + + function is_char(character) { + var bool = false; + all.filter(function (i) { + bool = (i === character); + }); + return bool; + } + + function heComes(text, options) { + var result = '', counts, l; + options = options || {}; + options["up"] = options["up"] || true; + options["mid"] = options["mid"] || true; + options["down"] = options["down"] || true; + options["size"] = options["size"] || "maxi"; + text = text.split(''); + for (l in text) { + if (is_char(l)) { + continue; + } + result = result + text[l]; + counts = {"up" : 0, "down" : 0, "mid" : 0}; + switch (options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.min = randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.min = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down = randomNumber(8) + 1; + break; + } + + var arr = ["up", "mid", "down"]; + for (var d in arr) { + var index = arr[d]; + for (var i = 0 ; i <= counts[index]; i++) { + if (options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + } + return heComes(text); +} + + +// don't summon zalgo +addProperty('zalgo', function () { + return zalgo(this); +}); diff --git a/node_modules/grunt/node_modules/colors/example.html b/node_modules/grunt/node_modules/colors/example.html new file mode 100644 index 000000000..7a2ae605f --- /dev/null +++ b/node_modules/grunt/node_modules/colors/example.html @@ -0,0 +1,76 @@ + + + + + Colors Example + + + + + + \ No newline at end of file diff --git a/node_modules/grunt/node_modules/colors/example.js b/node_modules/grunt/node_modules/colors/example.js new file mode 100644 index 000000000..b1e03a4fa --- /dev/null +++ b/node_modules/grunt/node_modules/colors/example.js @@ -0,0 +1,77 @@ +var colors = require('./colors'); + +//colors.mode = "browser"; + +var test = colors.red("hopefully colorless output"); +console.log('Rainbows are fun!'.rainbow); +console.log('So '.italic + 'are'.underline + ' styles! '.bold + 'inverse'.inverse); // styles not widely supported +console.log('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported +//console.log('zalgo time!'.zalgo); +console.log(test.stripColors); +console.log("a".grey + " b".black); +console.log("Zebras are so fun!".zebra); +console.log('background color attack!'.black.whiteBG) + +// +// Remark: .strikethrough may not work with Mac OS Terminal App +// +console.log("This is " + "not".strikethrough + " fun."); +console.log(colors.rainbow('Rainbows are fun!')); +console.log(colors.italic('So ') + colors.underline('are') + colors.bold(' styles! ') + colors.inverse('inverse')); // styles not widely supported +console.log(colors.bold(colors.italic(colors.underline(colors.red('Chains are also cool.'))))); // styles not widely supported +//console.log(colors.zalgo('zalgo time!')); +console.log(colors.stripColors(test)); +console.log(colors.grey("a") + colors.black(" b")); + +colors.addSequencer("america", function(letter, i, exploded) { + if(letter === " ") return letter; + switch(i%3) { + case 0: return letter.red; + case 1: return letter.white; + case 2: return letter.blue; + } +}); + +colors.addSequencer("random", (function() { + var available = ['bold', 'underline', 'italic', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; + + return function(letter, i, exploded) { + return letter === " " ? letter : letter[available[Math.round(Math.random() * (available.length - 1))]]; + }; +})()); + +console.log("AMERICA! F--K YEAH!".america); +console.log("So apparently I've been to Mars, with all the little green men. But you know, I don't recall.".random); + +// +// Custom themes +// + +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); + +// outputs grey text +console.log("this is an input".input); + +// Load a theme from file +colors.setTheme('./themes/winston-dark.js'); + +console.log("this is an input".input); + diff --git a/node_modules/grunt/node_modules/colors/package.json b/node_modules/grunt/node_modules/colors/package.json new file mode 100644 index 000000000..6dca75e71 --- /dev/null +++ b/node_modules/grunt/node_modules/colors/package.json @@ -0,0 +1,33 @@ +{ + "name": "colors", + "description": "get colors in your node.js console like what", + "version": "0.6.2", + "author": { + "name": "Marak Squires" + }, + "homepage": "https://github.com/Marak/colors.js", + "bugs": { + "url": "https://github.com/Marak/colors.js/issues" + }, + "keywords": [ + "ansi", + "terminal", + "colors" + ], + "repository": { + "type": "git", + "url": "http://github.com/Marak/colors.js.git" + }, + "engines": { + "node": ">=0.1.90" + }, + "main": "colors", + "readme": "# colors.js - get color and style in your node.js console ( and browser ) like what\n\n\n\n\n## Installation\n\n npm install colors\n\n## colors and styles!\n\n- bold\n- italic\n- underline\n- inverse\n- yellow\n- cyan\n- white\n- magenta\n- green\n- red\n- grey\n- blue\n- rainbow\n- zebra\n- random\n\n## Usage\n\n``` js\nvar colors = require('./colors');\n\nconsole.log('hello'.green); // outputs green text\nconsole.log('i like cake and pies'.underline.red) // outputs red underlined text\nconsole.log('inverse the color'.inverse); // inverses the color\nconsole.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces)\n```\n\n# Creating Custom themes\n\n```js\n\nvar colors = require('colors');\n\ncolors.setTheme({\n silly: 'rainbow',\n input: 'grey',\n verbose: 'cyan',\n prompt: 'grey',\n info: 'green',\n data: 'grey',\n help: 'cyan',\n warn: 'yellow',\n debug: 'blue',\n error: 'red'\n});\n\n// outputs red text\nconsole.log(\"this is an error\".error);\n\n// outputs yellow text\nconsole.log(\"this is a warning\".warn);\n```\n\n\n### Contributors \n\nMarak (Marak Squires)\nAlexis Sellier (cloudhead)\nmmalecki (Maciej Małecki)\nnicoreed (Nico Reed)\nmorganrallen (Morgan Allen)\nJustinCampbell (Justin Campbell)\nded (Dustin Diaz)\n\n\n#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded)\n", + "readmeFilename": "ReadMe.md", + "_id": "colors@0.6.2", + "dist": { + "shasum": "20f81061b635cd05ffc2a02e884a763d82dba0a6" + }, + "_from": "colors@~0.6.0-1", + "_resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" +} diff --git a/node_modules/grunt/node_modules/colors/test.js b/node_modules/grunt/node_modules/colors/test.js new file mode 100644 index 000000000..c32417d62 --- /dev/null +++ b/node_modules/grunt/node_modules/colors/test.js @@ -0,0 +1,70 @@ +var assert = require('assert'), + colors = require('./colors'); + +var s = 'string'; + +function a(s, code) { + return '\x1B[' + code.toString() + 'm' + s + '\x1B[39m'; +} + +function aE(s, color, code) { + assert.equal(s[color], a(s, code)); + assert.equal(colors[color](s), a(s, code)); + assert.equal(s[color], colors[color](s)); + assert.equal(s[color].stripColors, s); + assert.equal(s[color].stripColors, colors.stripColors(s)); +} + +function h(s, color) { + return '' + s + ''; +} + +var stylesColors = ['white', 'black', 'blue', 'cyan', 'green', 'magenta', 'red', 'yellow']; +var stylesAll = stylesColors.concat(['bold', 'italic', 'underline', 'inverse', 'rainbow']); + +colors.mode = 'console'; +assert.equal(s.bold, '\x1B[1m' + s + '\x1B[22m'); +assert.equal(s.italic, '\x1B[3m' + s + '\x1B[23m'); +assert.equal(s.underline, '\x1B[4m' + s + '\x1B[24m'); +assert.equal(s.strikethrough, '\x1B[9m' + s + '\x1B[29m'); +assert.equal(s.inverse, '\x1B[7m' + s + '\x1B[27m'); +assert.ok(s.rainbow); +aE(s, 'white', 37); +aE(s, 'grey', 90); +aE(s, 'black', 30); +aE(s, 'blue', 34); +aE(s, 'cyan', 36); +aE(s, 'green', 32); +aE(s, 'magenta', 35); +aE(s, 'red', 31); +aE(s, 'yellow', 33); +assert.equal(s, 'string'); + +colors.setTheme({error:'red'}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); + +colors.mode = 'browser'; +assert.equal(s.bold, '' + s + ''); +assert.equal(s.italic, '' + s + ''); +assert.equal(s.underline, '' + s + ''); +assert.equal(s.strikethrough, '' + s + ''); +assert.equal(s.inverse, '' + s + ''); +assert.ok(s.rainbow); +stylesColors.forEach(function (color) { + assert.equal(s[color], h(s, color)); + assert.equal(colors[color](s), h(s, color)); +}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); + +colors.mode = 'none'; +stylesAll.forEach(function (style) { + assert.equal(s[style], s); + assert.equal(colors[style](s), s); +}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); diff --git a/node_modules/grunt/node_modules/colors/themes/winston-dark.js b/node_modules/grunt/node_modules/colors/themes/winston-dark.js new file mode 100644 index 000000000..49a905ba4 --- /dev/null +++ b/node_modules/grunt/node_modules/colors/themes/winston-dark.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'black', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/node_modules/grunt/node_modules/colors/themes/winston-light.js b/node_modules/grunt/node_modules/colors/themes/winston-light.js new file mode 100644 index 000000000..571972c1b --- /dev/null +++ b/node_modules/grunt/node_modules/colors/themes/winston-light.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/node_modules/grunt/node_modules/dateformat/Readme.md b/node_modules/grunt/node_modules/dateformat/Readme.md new file mode 100644 index 000000000..d469e6d78 --- /dev/null +++ b/node_modules/grunt/node_modules/dateformat/Readme.md @@ -0,0 +1,67 @@ +# node-dateformat + +A node.js package for Steven Levithan's excellent [dateFormat()][dateformat] function. + +## Modifications + +* Removed the `Date.prototype.format` method. Sorry folks, but extending native prototypes is for suckers. +* Added a `module.exports = dateFormat;` statement at the bottom + +## Usage + +As taken from Steven's post, modified to match the Modifications listed above: + + var dateFormat = require('dateformat'); + var now = new Date(); + + // Basic usage + dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT"); + // Saturday, June 9th, 2007, 5:46:21 PM + + // You can use one of several named masks + dateFormat(now, "isoDateTime"); + // 2007-06-09T17:46:21 + + // ...Or add your own + dateFormat.masks.hammerTime = 'HH:MM! "Can\'t touch this!"'; + dateFormat(now, "hammerTime"); + // 17:46! Can't touch this! + + // When using the standalone dateFormat function, + // you can also provide the date as a string + dateFormat("Jun 9 2007", "fullDate"); + // Saturday, June 9, 2007 + + // Note that if you don't include the mask argument, + // dateFormat.masks.default is used + dateFormat(now); + // Sat Jun 09 2007 17:46:21 + + // And if you don't include the date argument, + // the current date and time is used + dateFormat(); + // Sat Jun 09 2007 17:46:22 + + // You can also skip the date argument (as long as your mask doesn't + // contain any numbers), in which case the current date/time is used + dateFormat("longTime"); + // 5:46:22 PM EST + + // And finally, you can convert local time to UTC time. Simply pass in + // true as an additional argument (no argument skipping allowed in this case): + dateFormat(now, "longTime", true); + // 10:46:21 PM UTC + + // ...Or add the prefix "UTC:" to your mask. + dateFormat(now, "UTC:h:MM:ss TT Z"); + // 10:46:21 PM UTC + + // You can also get the ISO 8601 week of the year: + dateFormat(now, "W"); + // 42 +## License + +(c) 2007-2009 Steven Levithan [stevenlevithan.com][stevenlevithan], MIT license. + +[dateformat]: http://blog.stevenlevithan.com/archives/date-time-format +[stevenlevithan]: http://stevenlevithan.com/ diff --git a/node_modules/grunt/node_modules/dateformat/lib/dateformat.js b/node_modules/grunt/node_modules/dateformat/lib/dateformat.js new file mode 100644 index 000000000..92294246b --- /dev/null +++ b/node_modules/grunt/node_modules/dateformat/lib/dateformat.js @@ -0,0 +1,165 @@ +/* + * Date Format 1.2.3 + * (c) 2007-2009 Steven Levithan + * MIT license + * + * Includes enhancements by Scott Trenda + * and Kris Kowal + * + * Accepts a date, a mask, or a date and a mask. + * Returns a formatted version of the given date. + * The date defaults to the current date/time. + * The mask defaults to dateFormat.masks.default. + */ + +var dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZW]|"[^"]*"|'[^']*'/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }, + /** + * Get the ISO 8601 week number + * Based on comments from + * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html + */ + getWeek = function (date) { + // Remove time components of date + var targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + + // Change date to Thursday same week + targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3); + + // Take January 4th as it is always in week 1 (see ISO 8601) + var firstThursday = new Date(targetThursday.getFullYear(), 0, 4); + + // Change date to Thursday same week + firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3); + + // Check if daylight-saving-time-switch occured and correct for it + var ds = targetThursday.getTimezoneOffset()/firstThursday.getTimezoneOffset()-1; + targetThursday.setHours(targetThursday.getHours()+ds); + + // Number of weeks between target Thursday and first Thursday + var weekDiff = (targetThursday - firstThursday) / (86400000*7); + return 1 + weekDiff; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + date = date || new Date; + + if(!(date instanceof Date)) { + date = new Date(date); + } + + if (isNaN(date)) { + throw TypeError("Invalid date"); + } + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + W = getWeek(date), + flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10], + W: W + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; +}(); + +// Some common format strings +dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" +}; + +// Internationalization strings +dateFormat.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ] +}; + +/* +// For convenience... +Date.prototype.format = function (mask, utc) { + return dateFormat(this, mask, utc); +}; +*/ + +if (typeof exports !== "undefined") { + module.exports = dateFormat; +} diff --git a/node_modules/grunt/node_modules/dateformat/package.json b/node_modules/grunt/node_modules/dateformat/package.json new file mode 100644 index 000000000..7e8fda428 --- /dev/null +++ b/node_modules/grunt/node_modules/dateformat/package.json @@ -0,0 +1,24 @@ +{ + "name": "dateformat", + "description": "A node.js package for Steven Levithan's excellent dateFormat() function.", + "maintainers": "Felix Geisendörfer ", + "homepage": "https://github.com/felixge/node-dateformat", + "author": { + "name": "Steven Levithan" + }, + "version": "1.0.2-1.2.3", + "main": "./lib/dateformat", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# node-dateformat\n\nA node.js package for Steven Levithan's excellent [dateFormat()][dateformat] function.\n\n## Modifications\n\n* Removed the `Date.prototype.format` method. Sorry folks, but extending native prototypes is for suckers.\n* Added a `module.exports = dateFormat;` statement at the bottom\n\n## Usage\n\nAs taken from Steven's post, modified to match the Modifications listed above:\n\n var dateFormat = require('dateformat');\n var now = new Date();\n\n // Basic usage\n dateFormat(now, \"dddd, mmmm dS, yyyy, h:MM:ss TT\");\n // Saturday, June 9th, 2007, 5:46:21 PM\n\n // You can use one of several named masks\n dateFormat(now, \"isoDateTime\");\n // 2007-06-09T17:46:21\n\n // ...Or add your own\n dateFormat.masks.hammerTime = 'HH:MM! \"Can\\'t touch this!\"';\n dateFormat(now, \"hammerTime\");\n // 17:46! Can't touch this!\n\n // When using the standalone dateFormat function,\n // you can also provide the date as a string\n dateFormat(\"Jun 9 2007\", \"fullDate\");\n // Saturday, June 9, 2007\n\n // Note that if you don't include the mask argument,\n // dateFormat.masks.default is used\n dateFormat(now);\n // Sat Jun 09 2007 17:46:21\n\n // And if you don't include the date argument,\n // the current date and time is used\n dateFormat();\n // Sat Jun 09 2007 17:46:22\n\n // You can also skip the date argument (as long as your mask doesn't\n // contain any numbers), in which case the current date/time is used\n dateFormat(\"longTime\");\n // 5:46:22 PM EST\n\n // And finally, you can convert local time to UTC time. Simply pass in\n // true as an additional argument (no argument skipping allowed in this case):\n dateFormat(now, \"longTime\", true);\n // 10:46:21 PM UTC\n\n // ...Or add the prefix \"UTC:\" to your mask.\n dateFormat(now, \"UTC:h:MM:ss TT Z\");\n // 10:46:21 PM UTC\n\n // You can also get the ISO 8601 week of the year:\n dateFormat(now, \"W\");\n // 42\n## License\n\n(c) 2007-2009 Steven Levithan [stevenlevithan.com][stevenlevithan], MIT license.\n\n[dateformat]: http://blog.stevenlevithan.com/archives/date-time-format\n[stevenlevithan]: http://stevenlevithan.com/\n", + "readmeFilename": "Readme.md", + "_id": "dateformat@1.0.2-1.2.3", + "dist": { + "shasum": "72e2a36fb961026179bc4ba0ce4ca83beb975280" + }, + "_from": "dateformat@1.0.2-1.2.3", + "_resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz" +} diff --git a/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.js b/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.js new file mode 100644 index 000000000..d1ddbe818 --- /dev/null +++ b/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.js @@ -0,0 +1,4 @@ +var dateFormat = require('../lib/dateformat.js'); + +var val = process.argv[2] || new Date(); +console.log(dateFormat(val, 'W')); diff --git a/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.sh b/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.sh new file mode 100644 index 000000000..3c3e69b31 --- /dev/null +++ b/node_modules/grunt/node_modules/dateformat/test/test_weekofyear.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# this just takes php's date() function as a reference to check if week of year +# is calculated correctly in the range from 1970 .. 2038 by brute force... + +SEQ="seq" +SYSTEM=`uname` +if [ "$SYSTEM" = "Darwin" ]; then + SEQ="jot" +fi + +for YEAR in {1970..2038}; do + for MONTH in {1..12}; do + DAYS=$(cal $MONTH $YEAR | egrep "28|29|30|31" |tail -1 |awk '{print $NF}') + for DAY in $( $SEQ $DAYS ); do + DATE=$YEAR-$MONTH-$DAY + echo -n $DATE ... + NODEVAL=$(node test_weekofyear.js $DATE) + PHPVAL=$(php -r "echo intval(date('W', strtotime('$DATE')));") + if [ "$NODEVAL" -ne "$PHPVAL" ]; then + echo "MISMATCH: node: $NODEVAL vs php: $PHPVAL for date $DATE" + else + echo " OK" + fi + done + done +done diff --git a/node_modules/grunt/node_modules/eventemitter2/README.md b/node_modules/grunt/node_modules/eventemitter2/README.md new file mode 100644 index 000000000..9501fa3f3 --- /dev/null +++ b/node_modules/grunt/node_modules/eventemitter2/README.md @@ -0,0 +1,212 @@ +# EventEmitter2 + +EventEmitter2 is an implementation of the EventEmitter found in Node.js + +## Features + + - Namespaces/Wildcards. + - Times To Listen (TTL), extends the `once` concept with `many`. + - Browser environment compatibility. + - Demonstrates good performance in benchmarks + +``` +EventEmitterHeatUp x 3,728,965 ops/sec \302\2610.68% (60 runs sampled) +EventEmitter x 2,822,904 ops/sec \302\2610.74% (63 runs sampled) +EventEmitter2 x 7,251,227 ops/sec \302\2610.55% (58 runs sampled) +EventEmitter2 (wild) x 3,220,268 ops/sec \302\2610.44% (65 runs sampled) +Fastest is EventEmitter2 +``` + +## Differences (Non breaking, compatible with existing EventEmitter) + + - The constructor takes a configuration object. + +```javascript + var EventEmitter2 = require('eventemitter2').EventEmitter2; + var server = new EventEmitter2({ + wildcard: true, // should the event emitter use wildcards. + delimiter: '::', // the delimiter used to segment namespaces, defaults to `.`. + newListener: false, // if you want to emit the newListener event set to true. + maxListeners: 20, // the max number of listeners that can be assigned to an event, defaults to 10. + }); +``` + + - Getting the actual event that fired. + +```javascript + server.on('foo.*', function(value1, value2) { + console.log(this.event, value1, value2); + }); +``` + + - Fire an event N times and then remove it, an extension of the `once` concept. + +```javascript + server.many('foo', 4, function() { + console.log('hello'); + }); +``` + + - Pass in a namespaced event as an array rather than a delimited string. + +```javascript + server.many(['foo', 'bar', 'bazz'], function() { + console.log('hello'); + }); +``` + + +## API + +When an `EventEmitter` instance experiences an error, the typical action is +to emit an `error` event. Error events are treated as a special case. +If there is no listener for it, then the default action is to print a stack +trace and exit the program. + +All EventEmitters emit the event `newListener` when new listeners are +added. + + +**Namespaces** with **Wildcards** +To use namespaces/wildcards, pass the `wildcard` option into the EventEmitter constructor. +When namespaces/wildcards are enabled, events can either be strings (`foo.bar`) separated +by a delimiter or arrays (`['foo', 'bar']`). The delimiter is also configurable as a +constructor option. + +An event name passed to any event emitter method can contain a wild card (the `*` character). +If the event name is a string, a wildcard may appear as `foo.*`. If the event name is an array, +the wildcard may appear as `['foo', '*']`. + +If either of the above described events were passed to the `on` method, subsequent emits such +as the following would be observed... + +```javascript + emitter.emit('foo.bazz'); + emitter.emit(['foo', 'bar']); +``` + + +#### emitter.addListener(event, listener) +#### emitter.on(event, listener) + +Adds a listener to the end of the listeners array for the specified event. + +```javascript + server.on('data', function(value1, value2, value3 /* accepts any number of expected values... */) { + console.log('The event was raised!'); + }); +``` + +```javascript + server.on('data', function(value) { + console.log('The event was raised!'); + }); +``` + +#### emitter.onAny(listener) + +Adds a listener that will be fired when any event is emitted. + +```javascript + server.onAny(function(value) { + console.log('All events trigger this.'); + }); +``` + +#### emitter.offAny(listener) + +Removes the listener that will be fired when any event is emitted. + +```javascript + server.offAny(function(value) { + console.log('The event was raised!'); + }); +``` + +#### emitter.once(event, listener) + +Adds a **one time** listener for the event. The listener is invoked only the first time the event is fired, after which it is removed. + +```javascript + server.once('get', function (value) { + console.log('Ah, we have our first value!'); + }); +``` + +#### emitter.many(event, timesToListen, listener) + +Adds a listener that will execute **n times** for the event before being removed. The listener is invoked only the first time the event is fired, after which it is removed. + +```javascript + server.many('get', 4, function (value) { + console.log('This event will be listened to exactly four times.'); + }); +``` + + +#### emitter.removeListener(event, listener) +#### emitter.off(event, listener) + +Remove a listener from the listener array for the specified event. **Caution**: changes array indices in the listener array behind the listener. + +```javascript + var callback = function(value) { + console.log('someone connected!'); + }; + server.on('get', callback); + // ... + server.removeListener('get', callback); +``` + + +#### emitter.removeAllListeners([event]) + +Removes all listeners, or those of the specified event. + + +#### emitter.setMaxListeners(n) + +By default EventEmitters will print a warning if more than 10 listeners are added to it. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited. + + +#### emitter.listeners(event) + +Returns an array of listeners for the specified event. This array can be manipulated, e.g. to remove listeners. + +```javascript + server.on('get', function(value) { + console.log('someone connected!'); + }); + console.log(console.log(server.listeners('get')); // [ [Function] ] +``` + +#### emitter.listenersAny() + +Returns an array of listeners that are listening for any event that is specified. This array can be manipulated, e.g. to remove listeners. + +```javascript + server.onAny(function(value) { + console.log('someone connected!'); + }); + console.log(console.log(server.listenersAny()[0]); // [ [Function] ] // someone connected! +``` + +#### emitter.emit(event, [arg1], [arg2], [...]) + +Execute each of the listeners that may be listening for the specified event name in order with the list of arguments. + +## Test coverage + +There is a test suite that tries to cover each use case, it can be found here. + +## Licence + +(The MIT License) + +Copyright (c) 2011 hij1nx + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/eventemitter2/index.js b/node_modules/grunt/node_modules/eventemitter2/index.js new file mode 100644 index 000000000..6f583b5f6 --- /dev/null +++ b/node_modules/grunt/node_modules/eventemitter2/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/eventemitter2'); diff --git a/node_modules/grunt/node_modules/eventemitter2/lib/eventemitter2.js b/node_modules/grunt/node_modules/eventemitter2/lib/eventemitter2.js new file mode 100644 index 000000000..dc9849ec5 --- /dev/null +++ b/node_modules/grunt/node_modules/eventemitter2/lib/eventemitter2.js @@ -0,0 +1,561 @@ +;!function(exports, undefined) { + + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + conf.maxListeners && (this._events.maxListeners = conf.maxListeners); + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this.newListener = conf.newListener); + + if (this.wildcard) { + this.listenerTree = {}; + } + } + } + + function EventEmitter(conf) { + this._events = {}; + this.newListener = false; + configure.call(this, conf); + } + + // + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i) { + if (!tree) { + return []; + } + var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached, + typeLength = type.length, currentType = type[i], nextType = type[i+1]; + if (i === typeLength && tree._listeners) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + return [tree]; + } else { + for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) { + handlers && handlers.push(tree._listeners[leaf]); + } + return [tree]; + } + } + + if ((currentType === '*' || currentType === '**') || tree[currentType]) { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + if (currentType === '*') { + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1)); + } + } + return listeners; + } else if(currentType === '**') { + endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*')); + if(endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength)); + } + + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + if(branch === '*' || branch === '**') { + if(tree[branch]._listeners && !endReached) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength)); + } + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } else if(branch === nextType) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2)); + } else { + // No match on this one, shift into the tree but not in the type array. + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } + } + } + return listeners; + } + + listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1)); + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i+1); + } + + xxTree = tree['**']; + if(xxTree) { + if(i < typeLength) { + if(xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength); + } + + // Build arrays of matching next branches and others. + for(branch in xxTree) { + if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) { + if(branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i+2); + } else if(branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i+1); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1); + } + } + } + } else if(xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength); + } else if(xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener) { + + type = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + for(var i = 0, len = type.length; i+1 < len; i++) { + if(type[i] === '**' && type[i+1] === '**') { + return; + } + } + + var tree = this.listenerTree; + var name = type.shift(); + + while (name) { + + if (!tree[name]) { + tree[name] = {}; + } + + tree = tree[name]; + + if (type.length === 0) { + + if (!tree._listeners) { + tree._listeners = listener; + } + else if(typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners, listener]; + } + else if (isArray(tree._listeners)) { + + tree._listeners.push(listener); + + if (!tree._listeners.warned) { + + var m = defaultMaxListeners; + + if (typeof this._events.maxListeners !== 'undefined') { + m = this._events.maxListeners; + } + + if (m > 0 && tree._listeners.length > m) { + + tree._listeners.warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + tree._listeners.length); + console.trace(); + } + } + } + return true; + } + name = type.shift(); + } + return true; + } + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + this._events || init.call(this); + this._events.maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + }; + + EventEmitter.prototype.event = ''; + + EventEmitter.prototype.once = function(event, fn) { + this.many(event, 1, fn); + return this; + }; + + EventEmitter.prototype.many = function(event, ttl, fn) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + fn.apply(this, arguments); + } + + listener._origin = fn; + + this.on(event, listener); + + return self; + }; + + EventEmitter.prototype.emit = function() { + + this._events || init.call(this); + + var type = arguments[0]; + + if (type === 'newListener' && !this.newListener) { + if (!this._events.newListener) { return false; } + } + + // Loop through the *_all* functions and invoke them. + if (this._all) { + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + this._all[i].apply(this, args); + } + } + + // If there is no 'error' event listener then throw. + if (type === 'error') { + + if (!this._all && + !this._events.error && + !(this.wildcard && this.listenerTree.error)) { + + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + return false; + } + } + + var handler; + + if(this.wildcard) { + handler = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } + else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + if (arguments.length === 1) { + handler.call(this); + } + else if (arguments.length > 1) + switch (arguments.length) { + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + handler.apply(this, args); + } + return true; + } + else if (handler) { + var l = arguments.length; + var args = new Array(l - 1); + for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; + + var listeners = handler.slice(); + for (var i = 0, l = listeners.length; i < l; i++) { + this.event = type; + listeners[i].apply(this, args); + } + return (listeners.length > 0) || this._all; + } + else { + return this._all; + } + + }; + + EventEmitter.prototype.on = function(type, listener) { + + if (typeof type === 'function') { + this.onAny(type); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + this.emit('newListener', type, listener); + + if(this.wildcard) { + growListenerTree.call(this, type, listener); + return this; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } + else if(typeof this._events[type] === 'function') { + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + } + else if (isArray(this._events[type])) { + // If we've already got an array, just append. + this._events[type].push(listener); + + // Check for listener leak + if (!this._events[type].warned) { + + var m = defaultMaxListeners; + + if (typeof this._events.maxListeners !== 'undefined') { + m = this._events.maxListeners; + } + + if (m > 0 && this._events[type].length > m) { + + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + console.trace(); + } + } + } + return this; + }; + + EventEmitter.prototype.onAny = function(fn) { + + if(!this._all) { + this._all = []; + } + + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + // Add the function to the event listener collection. + this._all.push(fn); + return this; + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + } + else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + return this; + } + } + } else { + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function(type) { + if (arguments.length === 0) { + !this._events || init.call(this); + return this; + } + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + + for (var iLeaf=0; iLeaf= 0.2.2" + }, + "main": "./lib/eventemitter2.js", + "scripts": { + "test": "nodeunit test/simple/ && nodeunit test/wildcardEvents/", + "benchmark": "node test/perf/benchmark.js" + }, + "files": [ + "lib/eventemitter2.js", + "index.js" + ], + "readme": "# EventEmitter2\n\nEventEmitter2 is an implementation of the EventEmitter found in Node.js\n\n## Features\n\n - Namespaces/Wildcards.\n - Times To Listen (TTL), extends the `once` concept with `many`.\n - Browser environment compatibility.\n - Demonstrates good performance in benchmarks\n\n```\nEventEmitterHeatUp x 3,728,965 ops/sec \\302\\2610.68% (60 runs sampled)\nEventEmitter x 2,822,904 ops/sec \\302\\2610.74% (63 runs sampled)\nEventEmitter2 x 7,251,227 ops/sec \\302\\2610.55% (58 runs sampled)\nEventEmitter2 (wild) x 3,220,268 ops/sec \\302\\2610.44% (65 runs sampled)\nFastest is EventEmitter2\n```\n\n## Differences (Non breaking, compatible with existing EventEmitter)\n\n - The constructor takes a configuration object.\n \n```javascript\n var EventEmitter2 = require('eventemitter2').EventEmitter2;\n var server = new EventEmitter2({\n wildcard: true, // should the event emitter use wildcards.\n delimiter: '::', // the delimiter used to segment namespaces, defaults to `.`.\n newListener: false, // if you want to emit the newListener event set to true.\n maxListeners: 20, // the max number of listeners that can be assigned to an event, defaults to 10.\n });\n```\n\n - Getting the actual event that fired.\n\n```javascript\n server.on('foo.*', function(value1, value2) {\n console.log(this.event, value1, value2);\n });\n```\n\n - Fire an event N times and then remove it, an extension of the `once` concept.\n\n```javascript\n server.many('foo', 4, function() {\n console.log('hello');\n });\n```\n\n - Pass in a namespaced event as an array rather than a delimited string.\n\n```javascript\n server.many(['foo', 'bar', 'bazz'], function() {\n console.log('hello');\n });\n```\n\n\n## API\n\nWhen an `EventEmitter` instance experiences an error, the typical action is\nto emit an `error` event. Error events are treated as a special case.\nIf there is no listener for it, then the default action is to print a stack\ntrace and exit the program.\n\nAll EventEmitters emit the event `newListener` when new listeners are\nadded.\n\n\n**Namespaces** with **Wildcards**\nTo use namespaces/wildcards, pass the `wildcard` option into the EventEmitter constructor.\nWhen namespaces/wildcards are enabled, events can either be strings (`foo.bar`) separated\nby a delimiter or arrays (`['foo', 'bar']`). The delimiter is also configurable as a \nconstructor option.\n\nAn event name passed to any event emitter method can contain a wild card (the `*` character).\nIf the event name is a string, a wildcard may appear as `foo.*`. If the event name is an array, \nthe wildcard may appear as `['foo', '*']`.\n\nIf either of the above described events were passed to the `on` method, subsequent emits such \nas the following would be observed...\n\n```javascript\n emitter.emit('foo.bazz');\n emitter.emit(['foo', 'bar']);\n```\n\n\n#### emitter.addListener(event, listener)\n#### emitter.on(event, listener)\n\nAdds a listener to the end of the listeners array for the specified event.\n\n```javascript\n server.on('data', function(value1, value2, value3 /* accepts any number of expected values... */) {\n console.log('The event was raised!');\n });\n```\n\n```javascript\n server.on('data', function(value) {\n console.log('The event was raised!');\n });\n```\n\n#### emitter.onAny(listener)\n\nAdds a listener that will be fired when any event is emitted.\n\n```javascript\n server.onAny(function(value) {\n console.log('All events trigger this.');\n });\n```\n\n#### emitter.offAny(listener)\n\nRemoves the listener that will be fired when any event is emitted.\n\n```javascript\n server.offAny(function(value) {\n console.log('The event was raised!');\n });\n```\n\n#### emitter.once(event, listener)\n\nAdds a **one time** listener for the event. The listener is invoked only the first time the event is fired, after which it is removed.\n\n```javascript\n server.once('get', function (value) {\n console.log('Ah, we have our first value!');\n });\n```\n\n#### emitter.many(event, timesToListen, listener)\n\nAdds a listener that will execute **n times** for the event before being removed. The listener is invoked only the first time the event is fired, after which it is removed.\n\n```javascript\n server.many('get', 4, function (value) {\n console.log('This event will be listened to exactly four times.');\n });\n```\n\n\n#### emitter.removeListener(event, listener)\n#### emitter.off(event, listener)\n\nRemove a listener from the listener array for the specified event. **Caution**: changes array indices in the listener array behind the listener.\n\n```javascript\n var callback = function(value) {\n console.log('someone connected!');\n };\n server.on('get', callback);\n // ...\n server.removeListener('get', callback);\n```\n\n\n#### emitter.removeAllListeners([event])\n\nRemoves all listeners, or those of the specified event.\n\n\n#### emitter.setMaxListeners(n)\n\nBy default EventEmitters will print a warning if more than 10 listeners are added to it. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited.\n\n\n#### emitter.listeners(event)\n\nReturns an array of listeners for the specified event. This array can be manipulated, e.g. to remove listeners.\n\n```javascript\n server.on('get', function(value) {\n console.log('someone connected!');\n });\n console.log(console.log(server.listeners('get')); // [ [Function] ]\n```\n\n#### emitter.listenersAny()\n\nReturns an array of listeners that are listening for any event that is specified. This array can be manipulated, e.g. to remove listeners.\n\n```javascript\n server.onAny(function(value) {\n console.log('someone connected!');\n });\n console.log(console.log(server.listenersAny()[0]); // [ [Function] ] // someone connected!\n```\n\n#### emitter.emit(event, [arg1], [arg2], [...])\n\nExecute each of the listeners that may be listening for the specified event name in order with the list of arguments.\n\n## Test coverage\n\nThere is a test suite that tries to cover each use case, it can be found here.\n\n## Licence\n\n(The MIT License)\n\nCopyright (c) 2011 hij1nx \n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/hij1nx/EventEmitter2/issues" + }, + "_id": "eventemitter2@0.4.13", + "dist": { + "shasum": "b57c13f82638146612f72007d6d1c46fd93ffc8c" + }, + "_from": "eventemitter2@~0.4.9", + "_resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.13.tgz" +} diff --git a/node_modules/grunt/node_modules/findup-sync/.jshintrc b/node_modules/grunt/node_modules/findup-sync/.jshintrc new file mode 100644 index 000000000..6d171b894 --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/.jshintrc @@ -0,0 +1,16 @@ +{ + "loopfunc": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "unused": true, + "boss": true, + "eqnull": true, + "node": true, + "es5": true +} diff --git a/node_modules/grunt/node_modules/findup-sync/.npmignore b/node_modules/grunt/node_modules/findup-sync/.npmignore new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/findup-sync/Gruntfile.js b/node_modules/grunt/node_modules/findup-sync/Gruntfile.js new file mode 100644 index 000000000..2f964a5b4 --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/Gruntfile.js @@ -0,0 +1,25 @@ +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + nodeunit: { + files: ['test/**/*_test.js'], + }, + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] + } + }); + + // Load plugins. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + + // Default task. + grunt.registerTask('default', ['jshint', 'nodeunit']); + +}; diff --git a/node_modules/grunt/node_modules/findup-sync/LICENSE-MIT b/node_modules/grunt/node_modules/findup-sync/LICENSE-MIT new file mode 100644 index 000000000..bb2aad6dc --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2013 "Cowboy" Ben Alman + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/findup-sync/README.md b/node_modules/grunt/node_modules/findup-sync/README.md new file mode 100644 index 000000000..3b08b4e0f --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/README.md @@ -0,0 +1,44 @@ +# findup-sync + +Find the first file matching a given pattern in the current directory or the nearest ancestor directory. + +## Getting Started +Install the module with: `npm install findup-sync` + +```js +var findup = require('findup-sync'); + +// Start looking in the CWD. +var filepath1 = findup('{a,b}*.txt'); + +// Start looking somewhere else, and ignore case (probably a good idea). +var filepath2 = findup('{a,b}*.txt', {cwd: '/some/path', nocase: true}); +``` + +## Usage + +```js +findup(patternOrPatterns [, minimatchOptions]) +``` + +### patternOrPatterns +Type: `String` or `Array` +Default: none + +One or more wildcard glob patterns. Or just filenames. + +### minimatchOptions +Type: `Object` +Default: `{}` + +Options to be passed to [minimatch](https://github.com/isaacs/minimatch). + +Note that if you want to start in a different directory than the current working directory, specify a `cwd` property here. + +## Contributing +In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). + +## Release History +2013-03-08 - v0.1.2 - Updated dependencies. Fixed a Node 0.9.x bug. Updated unit tests to work cross-platform. +2012-11-15 - v0.1.1 - Now works without an options object. +2012-11-01 - v0.1.0 - Initial release. diff --git a/node_modules/grunt/node_modules/findup-sync/lib/findup-sync.js b/node_modules/grunt/node_modules/findup-sync/lib/findup-sync.js new file mode 100644 index 000000000..742a47814 --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/lib/findup-sync.js @@ -0,0 +1,46 @@ +/* + * findup-sync + * https://github.com/cowboy/node-findup-sync + * + * Copyright (c) 2013 "Cowboy" Ben Alman + * Licensed under the MIT license. + */ + +'use strict'; + +// Nodejs libs. +var path = require('path'); + +// External libs. +var glob = require('glob'); +var _ = require('lodash'); + +// Search for a filename in the given directory or all parent directories. +module.exports = function(patterns, options) { + // Normalize patterns to an array. + if (!Array.isArray(patterns)) { patterns = [patterns]; } + // Create globOptions so that it can be modified without mutating the + // original object. + var globOptions = Object.create(options || {}); + globOptions.maxDepth = 1; + globOptions.cwd = path.resolve(globOptions.cwd || '.'); + + var files, lastpath; + do { + // Search for files matching patterns. + files = _(patterns).map(function(pattern) { + return glob.sync(pattern, globOptions); + }).flatten().uniq().value(); + // Return file if found. + if (files.length > 0) { + return path.resolve(path.join(globOptions.cwd, files[0])); + } + // Go up a directory. + lastpath = globOptions.cwd; + globOptions.cwd = path.resolve(globOptions.cwd, '..'); + // If parentpath is the same as basedir, we can't go any higher. + } while (globOptions.cwd !== lastpath); + + // No files were found! + return null; +}; diff --git a/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/README.md b/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/README.md new file mode 100644 index 000000000..cac2c654e --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/README.md @@ -0,0 +1,164 @@ +# Lo-Dash v1.0.1 + +A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). + +## Download + +* Lo-Dash builds (for modern environments):
      +[Development](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.js) and +[Production](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.min.js) + +* Lo-Dash compatibility builds (for legacy and modern environments):
      +[Development](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.compat.js) and +[Production](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.compat.min.js) + +* Underscore compatibility builds:
      +[Development](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.underscore.js) and +[Production](https://raw.github.com/lodash/lodash/v1.0.1/dist/lodash.underscore.min.js) + +* CDN copies of ≤ v1.0.1’s builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):
      +[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.js), +[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.min.js),
      +[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.js), +[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.min.js),
      +[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.js), and +[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.min.js) + +* For optimal file size, [create a custom build](http://lodash.com/custom-builds) with only the features you need + +## Dive in + +We’ve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests). + +For a list of upcoming features, check out our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap). + +## Resources + +For more information check out these articles, screencasts, and other videos over Lo-Dash: + + * Posts + - [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/) + + * Videos + - [Introducing Lo-Dash](https://vimeo.com/44154599) + - [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601) + - [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600) + - [Unit testing in Lo-Dash](https://vimeo.com/45865290) + - [Lo-Dash’s approach to native method use](https://vimeo.com/48576012) + - [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk) + +## Features + + * AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.) + * [_(…)](http://lodash.com/docs#_) supports intuitive chaining + * [_.at](http://lodash.com/docs#at) for cherry-picking collection values + * [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods + * [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects + * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument + * [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early + * [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties + * [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties + * [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor + * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend) + * [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding + * [_.template](http://lodash.com/docs#template) supports [*“imports”* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * [_.where](http://lodash.com/docs#where) supports deep object comparisons + * [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick), + [and more…](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments + * [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray), + [and more…](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings + * [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map), + [and more…](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands + +## Support + +Lo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5. + +## Installation and usage + +In browsers: + +```html + +``` + +Using [`npm`](http://npmjs.org/): + +```bash +npm install lodash + +npm install -g lodash +npm link lodash +``` + +To avoid potential issues, update `npm` before installing Lo-Dash: + +```bash +npm install npm -g +``` + +In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/): + +```js +var _ = require('lodash'); + +// or as a drop-in replacement for Underscore +var _ = require('lodash/lodash.underscore'); +``` + +**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it. + +In [RingoJS v0.7.0-](http://ringojs.org/): + +```js +var _ = require('lodash')._; +``` + +In [Rhino](http://www.mozilla.org/rhino/): + +```js +load('lodash.js'); +``` + +In an AMD loader like [RequireJS](http://requirejs.org/): + +```js +require({ + 'paths': { + 'underscore': 'path/to/lodash' + } +}, +['underscore'], function(_) { + console.log(_.VERSION); +}); +``` + +## Release Notes + +### v1.0.1 + + * Add support for specifying source map URLs in `-p`/`--source-map` build options + * Ensured the second argument passed to `_.assign` is not treated as a `callback` + * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL` + * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed + * Made `_.defer` use `setImmediate`, in Node.js, when available + * Made `_.where` search arrays for values regardless of their index position + * Removed dead code from `_.template` + +The full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog). + +## BestieJS + +Lo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. + +## Author + +| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") | +|---| +| [John-David Dalton](http://allyoucanleet.com/) | + +## Contributors + +| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz "Follow @BlaineBublitz on Twitter") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") | +|---|---|---| +| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) | diff --git a/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/dist/lodash.compat.js b/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/dist/lodash.compat.js new file mode 100644 index 000000000..37ebc920b --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/node_modules/lodash/dist/lodash.compat.js @@ -0,0 +1,5152 @@ +/** + * @license + * Lo-Dash 1.0.1 (Custom Build) + * Build: `lodash -o ./dist/lodash.compat.js` + * Copyright 2012-2013 The Dojo Foundation + * Based on Underscore.js 1.4.4 + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. + * Available under MIT license + */ +;(function(window, undefined) { + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `module` */ + var freeModule = typeof module == 'object' && module && module.exports == freeExports && module; + + /** Detect free variable `global` and use it as `window` */ + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal) { + window = freeGlobal; + } + + /** Used for array and object method references */ + var arrayRef = [], + objectRef = {}; + + /** Used to generate unique IDs */ + var idCounter = 0; + + /** Used internally to indicate various things */ + var indicatorObject = objectRef; + + /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */ + var largeArraySize = 30; + + /** Used to restore the original `_` reference in `noConflict` */ + var oldDash = window._; + + /** Used to match HTML entities */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g; + + /** Used to match empty string literals in compiled template source */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match regexp flags from their coerced string values */ + var reFlags = /\w*$/; + + /** Used to detect if a method is native */ + var reNative = RegExp('^' + + (objectRef.valueOf + '') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + .replace(/valueOf|for [^\]]+/g, '.+?') + '$' + ); + + /** + * Used to match ES6 template delimiters + * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6 + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match "interpolate" template delimiters */ + var reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to ensure capturing order of template delimiters */ + var reNoMatch = /($^)/; + + /** Used to match HTML characters */ + var reUnescapedHtml = /[&<>"']/g; + + /** Used to match unescaped characters in compiled string literals */ + var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + + /** Used to fix the JScript [[DontEnum]] bug */ + var shadowed = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' + ]; + + /** Used to make template sourceURLs easier to identify */ + var templateCounter = 0; + + /** Native method shortcuts */ + var ceil = Math.ceil, + concat = arrayRef.concat, + floor = Math.floor, + getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, + hasOwnProperty = objectRef.hasOwnProperty, + push = arrayRef.push, + toString = objectRef.toString; + + /* Native method shortcuts for methods with the same name as other `lodash` methods */ + var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind, + nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, + nativeIsFinite = window.isFinite, + nativeIsNaN = window.isNaN, + nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys, + nativeMax = Math.max, + nativeMin = Math.min, + nativeRandom = Math.random; + + /** `Object#toString` result shortcuts */ + var argsClass = '[object Arguments]', + arrayClass = '[object Array]', + boolClass = '[object Boolean]', + dateClass = '[object Date]', + funcClass = '[object Function]', + numberClass = '[object Number]', + objectClass = '[object Object]', + regexpClass = '[object RegExp]', + stringClass = '[object String]'; + + /** Detect various environments */ + var isIeOpera = !!window.attachEvent, + isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera); + + /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */ + var isBindFast = nativeBind && !isV8; + + /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */ + var isKeysFast = nativeKeys && (isIeOpera || isV8); + + /** + * Detect the JScript [[DontEnum]] bug: + * + * In IE < 9 an objects own properties, shadowing non-enumerable ones, are + * made non-enumerable as well. + */ + var hasDontEnumBug; + + /** + * Detect if a `prototype` properties are enumerable by default: + * + * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + * (if the prototype or a property on the prototype has been set) + * incorrectly sets a function's `prototype` property [[Enumerable]] + * value to `true`. + */ + var hasEnumPrototype; + + /** Detect if own properties are iterated after inherited properties (IE < 9) */ + var iteratesOwnLast; + + /** + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * incorrectly: + * + * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` + * and `splice()` functions that fail to remove the last element, `value[0]`, + * of array-like objects even though the `length` property is set to `0`. + * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + */ + var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 }, + arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]); + + /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */ + var nonEnumArgs = true; + + (function() { + var props = []; + function ctor() { this.x = 1; } + ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var prop in new ctor) { props.push(prop); } + for (prop in arguments) { nonEnumArgs = !prop; } + + hasDontEnumBug = !/valueOf/.test(props); + hasEnumPrototype = ctor.propertyIsEnumerable('prototype'); + iteratesOwnLast = props[0] != 'x'; + }(1)); + + /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */ + var argsAreObjects = arguments.constructor == Object; + + /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */ + var noArgsClass = !isArguments(arguments); + + /** + * Detect lack of support for accessing string characters by index: + * + * IE < 8 can't access characters by index and IE 8 can only access + * characters by index on string literals. + */ + var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx'; + + /** + * Detect if a DOM node's [[Class]] is unresolvable (IE < 9) + * and that the JS engine won't error when attempting to coerce an object to + * a string without a `toString` function. + */ + try { + var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + ''); + } catch(e) { } + + /** Used to identify object classifications that `_.clone` supports */ + var cloneableClasses = {}; + cloneableClasses[funcClass] = false; + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[numberClass] = cloneableClasses[objectClass] = + cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + + /** Used to lookup a built-in constructor by [[Class]] */ + var ctorByClass = {}; + ctorByClass[arrayClass] = Array; + ctorByClass[boolClass] = Boolean; + ctorByClass[dateClass] = Date; + ctorByClass[objectClass] = Object; + ctorByClass[numberClass] = Number; + ctorByClass[regexpClass] = RegExp; + ctorByClass[stringClass] = String; + + /** Used to determine if values are of the language type Object */ + var objectTypes = { + 'boolean': false, + 'function': true, + 'object': true, + 'number': false, + 'string': false, + 'undefined': false + }; + + /** Used to escape characters for inclusion in compiled string literals */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object, that wraps the given `value`, to enable method + * chaining. + * + * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: + * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, + * and `unshift` + * + * The chainable wrapper functions are: + * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, + * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`, + * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`, + * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`, + * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, + * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip` + * + * The non-chainable wrapper functions are: + * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`, + * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, + * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, + * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, + * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`, + * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId` + * + * The wrapper functions `first` and `last` return wrapped values when `n` is + * passed, otherwise they return unwrapped values. + * + * @name _ + * @constructor + * @category Chaining + * @param {Mixed} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns a `lodash` instance. + */ + function lodash(value) { + // exit early if already wrapped, even if wrapped by a different `lodash` constructor + if (value && typeof value == 'object' && value.__wrapped__) { + return value; + } + // allow invoking `lodash` without the `new` operator + if (!(this instanceof lodash)) { + return new lodash(value); + } + this.__wrapped__ = value; + } + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in + * embedded Ruby (ERB). Change the following template settings to use alternative + * delimiters. + * + * @static + * @memberOf _ + * @type Object + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'escape': /<%-([\s\S]+?)%>/g, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'evaluate': /<%([\s\S]+?)%>/g, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type String + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type Object + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type Function + */ + '_': lodash + } + }; + + /*--------------------------------------------------------------------------*/ + + /** + * The template used to create iterator functions. + * + * @private + * @param {Obect} data The data object used to populate the text. + * @returns {String} Returns the interpolated text. + */ + var iteratorTemplate = function(obj) { + + var __p = 'var index, iterable = ' + + (obj.firstArg ) + + ', result = iterable;\nif (!iterable) return result;\n' + + (obj.top ) + + ';\n'; + if (obj.arrays) { + __p += 'var length = iterable.length; index = -1;\nif (' + + (obj.arrays ) + + ') { '; + if (obj.noCharByIndex) { + __p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } '; + } ; + __p += '\n while (++index < length) {\n ' + + (obj.loop ) + + '\n }\n}\nelse { '; + } else if (obj.nonEnumArgs) { + __p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' + + (obj.loop ) + + '\n }\n } else { '; + } ; + + if (obj.hasEnumPrototype) { + __p += '\n var skipProto = typeof iterable == \'function\';\n '; + } ; + + if (obj.isKeysFast && obj.useHas) { + __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n '; + if (obj.hasEnumPrototype) { + __p += 'if (!(skipProto && index == \'prototype\')) {\n '; + } ; + __p += + (obj.loop ) + + ''; + if (obj.hasEnumPrototype) { + __p += '}\n'; + } ; + __p += ' } '; + } else { + __p += '\n for (index in iterable) {'; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n if ('; + if (obj.hasEnumPrototype) { + __p += '!(skipProto && index == \'prototype\')'; + } if (obj.hasEnumPrototype && obj.useHas) { + __p += ' && '; + } if (obj.useHas) { + __p += 'hasOwnProperty.call(iterable, index)'; + } ; + __p += ') { '; + } ; + __p += + (obj.loop ) + + '; '; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n }'; + } ; + __p += '\n } '; + } ; + + if (obj.hasDontEnumBug) { + __p += '\n\n var ctor = iterable.constructor;\n '; + for (var k = 0; k < 7; k++) { + __p += '\n index = \'' + + (obj.shadowed[k] ) + + '\';\n if ('; + if (obj.shadowed[k] == 'constructor') { + __p += '!(ctor && ctor.prototype === iterable) && '; + } ; + __p += 'hasOwnProperty.call(iterable, index)) {\n ' + + (obj.loop ) + + '\n } '; + } ; + + } ; + + if (obj.arrays || obj.nonEnumArgs) { + __p += '\n}'; + } ; + __p += + (obj.bottom ) + + ';\nreturn result'; + + + return __p + }; + + /** Reusable iterator options for `assign` and `defaults` */ + var defaultsIteratorOptions = { + 'args': 'object, source, guard', + 'top': + 'var args = arguments,\n' + + ' argsIndex = 0,\n' + + " argsLength = typeof guard == 'number' ? 2 : args.length;\n" + + 'while (++argsIndex < argsLength) {\n' + + ' iterable = args[argsIndex];\n' + + ' if (iterable && objectTypes[typeof iterable]) {', + 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]", + 'bottom': ' }\n}' + }; + + /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */ + var eachIteratorOptions = { + 'args': 'collection, callback, thisArg', + 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)", + 'arrays': "typeof length == 'number'", + 'loop': 'if (callback(iterable[index], index, collection) === false) return result' + }; + + /** Reusable iterator options for `forIn` and `forOwn` */ + var forOwnIteratorOptions = { + 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top, + 'arrays': false + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function optimized to search large arrays for a given `value`, + * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`. + * + * @private + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=0] The index to search from. + * @param {Number} [largeSize=30] The length at which an array is considered large. + * @returns {Boolean} Returns `true`, if `value` is found, else `false`. + */ + function cachedContains(array, fromIndex, largeSize) { + fromIndex || (fromIndex = 0); + + var length = array.length, + isLarge = (length - fromIndex) >= (largeSize || largeArraySize); + + if (isLarge) { + var cache = {}, + index = fromIndex - 1; + + while (++index < length) { + // manually coerce `value` to a string because `hasOwnProperty`, in some + // older versions of Firefox, coerces objects incorrectly + var key = array[index] + ''; + (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]); + } + } + return function(value) { + if (isLarge) { + var key = value + ''; + return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1; + } + return indexOf(array, value, fromIndex) > -1; + } + } + + /** + * Used by `_.max` and `_.min` as the default `callback` when a given + * `collection` is a string value. + * + * @private + * @param {String} value The character to inspect. + * @returns {Number} Returns the code unit of given character. + */ + function charAtCallback(value) { + return value.charCodeAt(0); + } + + /** + * Used by `sortBy` to compare transformed `collection` values, stable sorting + * them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {Number} Returns the sort order indicator of `1` or `-1`. + */ + function compareAscending(a, b) { + var ai = a.index, + bi = b.index; + + a = a.criteria; + b = b.criteria; + + // ensure a stable sort in V8 and other engines + // http://code.google.com/p/v8/issues/detail?id=90 + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return ai < bi ? -1 : 1; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` binding + * of `thisArg` and prepends any `partialArgs` to the arguments passed to the + * bound function. + * + * @private + * @param {Function|String} func The function to bind or the method name. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Array} partialArgs An array of arguments to be partially applied. + * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right. + * @returns {Function} Returns the new bound function. + */ + function createBound(func, thisArg, partialArgs, rightIndicator) { + var isFunc = isFunction(func), + isPartial = !partialArgs, + key = thisArg; + + // juggle arguments + if (isPartial) { + partialArgs = thisArg; + } + if (!isFunc) { + thisArg = func; + } + + function bound() { + // `Function#bind` spec + // http://es5.github.com/#x15.3.4.5 + var args = arguments, + thisBinding = isPartial ? this : thisArg; + + if (!isFunc) { + func = thisArg[key]; + } + if (partialArgs.length) { + args = args.length + ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args)) + : partialArgs; + } + if (this instanceof bound) { + // ensure `new bound` is an instance of `bound` and `func` + noop.prototype = func.prototype; + thisBinding = new noop; + noop.prototype = null; + + // mimic the constructor's `return` behavior + // http://es5.github.com/#x13.2.2 + var result = func.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + } + return func.apply(thisBinding, args); + } + return bound; + } + + /** + * Produces a callback bound to an optional `thisArg`. If `func` is a property + * name, the created callback will return the property value for a given element. + * If `func` is an object, the created callback will return `true` for elements + * that contain the equivalent object properties, otherwise it will return `false`. + * + * @private + * @param {Mixed} [func=identity] The value to convert to a callback. + * @param {Mixed} [thisArg] The `this` binding of the created callback. + * @param {Number} [argCount=3] The number of arguments the callback accepts. + * @returns {Function} Returns a callback function. + */ + function createCallback(func, thisArg, argCount) { + if (func == null) { + return identity; + } + var type = typeof func; + if (type != 'function') { + if (type != 'object') { + return function(object) { + return object[func]; + }; + } + var props = keys(func); + return function(object) { + var length = props.length, + result = false; + while (length--) { + if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) { + break; + } + } + return result; + }; + } + if (typeof thisArg != 'undefined') { + if (argCount === 1) { + return function(value) { + return func.call(thisArg, value); + }; + } + if (argCount === 2) { + return function(a, b) { + return func.call(thisArg, a, b); + }; + } + if (argCount === 4) { + return function(accumulator, value, index, object) { + return func.call(thisArg, accumulator, value, index, object); + }; + } + return function(value, index, object) { + return func.call(thisArg, value, index, object); + }; + } + return func; + } + + /** + * Creates compiled iteration functions. + * + * @private + * @param {Object} [options1, options2, ...] The compile options object(s). + * arrays - A string of code to determine if the iterable is an array or array-like. + * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop. + * args - A string of comma separated arguments the iteration function will accept. + * top - A string of code to execute before the iteration branches. + * loop - A string of code to execute in the object loop. + * bottom - A string of code to execute after the iteration branches. + * + * @returns {Function} Returns the compiled function. + */ + function createIterator() { + var data = { + // support properties + 'hasDontEnumBug': hasDontEnumBug, + 'hasEnumPrototype': hasEnumPrototype, + 'isKeysFast': isKeysFast, + 'nonEnumArgs': nonEnumArgs, + 'noCharByIndex': noCharByIndex, + 'shadowed': shadowed, + + // iterator options + 'arrays': 'isArray(iterable)', + 'bottom': '', + 'loop': '', + 'top': '', + 'useHas': true + }; + + // merge options into a template data object + for (var object, index = 0; object = arguments[index]; index++) { + for (var key in object) { + data[key] = object[key]; + } + } + var args = data.args; + data.firstArg = /^[^,]+/.exec(args)[0]; + + // create the function factory + var factory = Function( + 'createCallback, hasOwnProperty, isArguments, isArray, isString, ' + + 'objectTypes, nativeKeys', + 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' + ); + // return the compiled function + return factory( + createCallback, hasOwnProperty, isArguments, isArray, isString, + objectTypes, nativeKeys + ); + } + + /** + * A function compiled to iterate `arguments` objects, arrays, objects, and + * strings consistenly across environments, executing the `callback` for each + * element in the `collection`. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). Callbacks may exit + * iteration early by explicitly returning `false`. + * + * @private + * @type Function + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + */ + var each = createIterator(eachIteratorOptions); + + /** + * Used by `template` to escape characters for inclusion in compiled + * string literals. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeStringChar(match) { + return '\\' + stringEscapes[match]; + } + + /** + * Used by `escape` to convert characters to HTML entities. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } + + /** + * Checks if `value` is a DOM node in IE < 9. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`. + */ + function isNode(value) { + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + } + + /** + * A no-operation function. + * + * @private + */ + function noop() { + // no operation performed + } + + /** + * Slices the `collection` from the `start` index up to, but not including, + * the `end` index. + * + * Note: This function is used, instead of `Array#slice`, to support node lists + * in IE < 9 and to ensure dense arrays are returned. + * + * @private + * @param {Array|Object|String} collection The collection to slice. + * @param {Number} start The start index. + * @param {Number} end The end index. + * @returns {Array} Returns the new array. + */ + function slice(array, start, end) { + start || (start = 0); + if (typeof end == 'undefined') { + end = array ? array.length : 0; + } + var index = -1, + length = end - start || 0, + result = Array(length < 0 ? 0 : length); + + while (++index < length) { + result[index] = array[start + index]; + } + return result; + } + + /** + * Used by `unescape` to convert HTML entities to characters. + * + * @private + * @param {String} match The matched character to unescape. + * @returns {String} Returns the unescaped character. + */ + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Checks if `value` is an `arguments` object. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`. + * @example + * + * (function() { return _.isArguments(arguments); })(1, 2, 3); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + function isArguments(value) { + return toString.call(value) == argsClass; + } + // fallback for browsers that can't detect `arguments` objects by [[Class]] + if (noArgsClass) { + isArguments = function(value) { + return value ? hasOwnProperty.call(value, 'callee') : false; + }; + } + + /** + * Iterates over `object`'s own and inherited enumerable properties, executing + * the `callback` for each property. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, key, object). Callbacks may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * function Dog(name) { + * this.name = name; + * } + * + * Dog.prototype.bark = function() { + * alert('Woof, woof!'); + * }; + * + * _.forIn(new Dog('Dagny'), function(value, key) { + * alert(key); + * }); + * // => alerts 'name' and 'bark' (order is not guaranteed) + */ + var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, { + 'useHas': false + }); + + /** + * Iterates over an object's own enumerable properties, executing the `callback` + * for each property. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, key, object). Callbacks may exit iteration early by explicitly + * returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * alert(key); + * }); + * // => alerts '0', '1', and 'length' (order is not guaranteed) + */ + var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions); + + /** + * Checks if `value` is an array. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`. + * @example + * + * (function() { return _.isArray(arguments); })(); + * // => false + * + * _.isArray([1, 2, 3]); + * // => true + */ + var isArray = nativeIsArray || function(value) { + // `instanceof` may cause a memory leak in IE 7 if `value` is a host object + // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak + return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass; + }; + + /** + * Creates an array composed of the own enumerable property names of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + * @example + * + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (order is not guaranteed) + */ + var keys = !nativeKeys ? shimKeys : function(object) { + if (!isObject(object)) { + return []; + } + if ((hasEnumPrototype && typeof object == 'function') || + (nonEnumArgs && object.length && isArguments(object))) { + return shimKeys(object); + } + return nativeKeys(object); + }; + + /** + * A fallback implementation of `isPlainObject` that checks if a given `value` + * is an object created by the `Object` constructor, assuming objects created + * by the `Object` constructor have no inherited enumerable properties and that + * there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + */ + function shimIsPlainObject(value) { + // avoid non-objects and false positives for `arguments` objects + var result = false; + if (!(value && typeof value == 'object') || isArguments(value)) { + return result; + } + // check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) { + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + if (iteratesOwnLast) { + forIn(value, function(value, key, object) { + result = !hasOwnProperty.call(object, key); + return false; + }); + return result === false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + forIn(value, function(value, key) { + result = key; + }); + return result === false || hasOwnProperty.call(value, result); + } + return result; + } + + /** + * A fallback implementation of `Object.keys` that produces an array of the + * given object's own enumerable property names. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + */ + function shimKeys(object) { + var result = []; + forOwn(object, function(value, key) { + result.push(key); + }); + return result; + } + + /** + * Used to convert characters to HTML entities: + * + * Though the `>` character is escaped for symmetry, characters like `>` and `/` + * don't require escaping in HTML and have no special meaning unless they're part + * of a tag or an unquoted attribute value. + * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to convert HTML entities to characters */ + var htmlUnescapes = invert(htmlEscapes); + + /*--------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources will overwrite propery assignments of previous + * sources. If a `callback` function is passed, it will be executed to produce + * the assigned values. The `callback` is bound to `thisArg` and invoked with + * two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @type Function + * @alias extend + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize assigning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the destination object. + * @example + * + * _.assign({ 'name': 'moe' }, { 'age': 40 }); + * // => { 'name': 'moe', 'age': 40 } + * + * var defaults = _.partialRight(_.assign, function(a, b) { + * return typeof a == 'undefined' ? b : a; + * }); + * + * var food = { 'name': 'apple' }; + * defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var assign = createIterator(defaultsIteratorOptions, { + 'top': + defaultsIteratorOptions.top.replace(';', + ';\n' + + "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" + + ' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' + + "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" + + ' callback = args[--argsLength];\n' + + '}' + ), + 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]' + }); + + /** + * Creates a clone of `value`. If `deep` is `true`, nested objects will also + * be cloned, otherwise they will be assigned by reference. If a `callback` + * function is passed, it will be executed to produce the cloned values. If + * `callback` returns `undefined`, cloning will be handled by the method instead. + * The `callback` is bound to `thisArg` and invoked with one argument; (value). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to clone. + * @param {Boolean} [deep=false] A flag to indicate a deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts. + * @returns {Mixed} Returns the cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var shallow = _.clone(stooges); + * shallow[0] === stooges[0]; + * // => true + * + * var deep = _.clone(stooges, true); + * deep[0] === stooges[0]; + * // => false + * + * _.mixin({ + * 'clone': _.partialRight(_.clone, function(value) { + * return _.isElement(value) ? value.cloneNode(false) : undefined; + * }) + * }); + * + * var clone = _.clone(document.body); + * clone.childNodes.length; + * // => 0 + */ + function clone(value, deep, callback, thisArg, stackA, stackB) { + var result = value; + + // allows working with "Collections" methods without using their `callback` + // argument, `index|key`, for this method's `callback` + if (typeof deep == 'function') { + thisArg = callback; + callback = deep; + deep = false; + } + if (typeof callback == 'function') { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1); + result = callback(result); + + var done = typeof result != 'undefined'; + if (!done) { + result = value; + } + } + // inspect [[Class]] + var isObj = isObject(result); + if (isObj) { + var className = toString.call(result); + if (!cloneableClasses[className] || (noNodeClass && isNode(result))) { + return result; + } + var isArr = isArray(result); + } + // shallow clone + if (!isObj || !deep) { + return isObj && !done + ? (isArr ? slice(result) : assign({}, result)) + : result; + } + var ctor = ctorByClass[className]; + switch (className) { + case boolClass: + case dateClass: + return done ? result : new ctor(+result); + + case numberClass: + case stringClass: + return done ? result : new ctor(result); + + case regexpClass: + return done ? result : ctor(result.source, reFlags.exec(result)); + } + // check for circular references and return corresponding clone + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // init cloned object + if (!done) { + result = isArr ? ctor(result.length) : {}; + + // add array properties assigned by `RegExp#exec` + if (isArr) { + if (hasOwnProperty.call(value, 'index')) { + result.index = value.index; + } + if (hasOwnProperty.call(value, 'input')) { + result.input = value.input; + } + } + } + // add the source value to the stack of traversed objects + // and associate it with its clone + stackA.push(value); + stackB.push(result); + + // recursively populate clone (susceptible to call stack limits) + (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) { + result[key] = clone(objValue, deep, callback, undefined, stackA, stackB); + }); + + return result; + } + + /** + * Creates a deep clone of `value`. If a `callback` function is passed, it will + * be executed to produce the cloned values. If `callback` returns the value it + * was passed, cloning will be handled by the method instead. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * Note: This function is loosely based on the structured clone algorithm. Functions + * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and + * objects created by constructors other than `Object` are cloned to plain `Object` objects. + * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the deep cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var deep = _.cloneDeep(stooges); + * deep[0] === stooges[0]; + * // => false + * + * var view = { + * 'label': 'docs', + * 'node': element + * }; + * + * var clone = _.cloneDeep(view, function(value) { + * return _.isElement(value) ? value.cloneNode(true) : value; + * }); + * + * clone.node == view.node; + * // => false + */ + function cloneDeep(value, callback, thisArg) { + return clone(value, true, callback, thisArg); + } + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property will be ignored. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param- {Object} [guard] Internally used to allow working with `_.reduce` + * without using its callback's `key` and `object` arguments as sources. + * @returns {Object} Returns the destination object. + * @example + * + * var food = { 'name': 'apple' }; + * _.defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var defaults = createIterator(defaultsIteratorOptions); + + /** + * Creates a sorted array of all enumerable properties, own and inherited, + * of `object` that have function values. + * + * @static + * @memberOf _ + * @alias methods + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names that have function values. + * @example + * + * _.functions(_); + * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + */ + function functions(object) { + var result = []; + forIn(object, function(value, key) { + if (isFunction(value)) { + result.push(key); + } + }); + return result.sort(); + } + + /** + * Checks if the specified object `property` exists and is a direct property, + * instead of an inherited property. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to check. + * @param {String} property The property to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + * @example + * + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); + * // => true + */ + function has(object, property) { + return object ? hasOwnProperty.call(object, property) : false; + } + + /** + * Creates an object composed of the inverted keys and values of the given `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to invert. + * @returns {Object} Returns the created inverted object. + * @example + * + * _.invert({ 'first': 'moe', 'second': 'larry' }); + * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed) + */ + function invert(object) { + var index = -1, + props = keys(object), + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + result[object[key]] = key; + } + return result; + } + + /** + * Checks if `value` is a boolean value. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`. + * @example + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || toString.call(value) == boolClass; + } + + /** + * Checks if `value` is a date. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + */ + function isDate(value) { + return value instanceof Date || toString.call(value) == dateClass; + } + + /** + * Checks if `value` is a DOM element. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + */ + function isElement(value) { + return value ? value.nodeType === 1 : false; + } + + /** + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object|String} value The value to inspect. + * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`. + * @example + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({}); + * // => true + * + * _.isEmpty(''); + * // => true + */ + function isEmpty(value) { + var result = true; + if (!value) { + return result; + } + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + className == argsClass || (noArgsClass && isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + return !length; + } + forOwn(value, function() { + return (result = false); + }); + return result; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent to each other. If `callback` is passed, it will be executed to + * compare values. If `callback` returns `undefined`, comparisons will be handled + * by the method instead. The `callback` is bound to `thisArg` and invoked with + * two arguments; (a, b). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} a The value to compare. + * @param {Mixed} b The other value to compare. + * @param {Function} [callback] The function to customize comparing values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [stackA=[]] Internally used track traversed `a` objects. + * @param- {Object} [stackB=[]] Internally used track traversed `b` objects. + * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`. + * @example + * + * var moe = { 'name': 'moe', 'age': 40 }; + * var copy = { 'name': 'moe', 'age': 40 }; + * + * moe == copy; + * // => false + * + * _.isEqual(moe, copy); + * // => true + * + * var words = ['hello', 'goodbye']; + * var otherWords = ['hi', 'goodbye']; + * + * _.isEqual(words, otherWords, function(a, b) { + * var reGreet = /^(?:hello|hi)$/i, + * aGreet = _.isString(a) && reGreet.test(a), + * bGreet = _.isString(b) && reGreet.test(b); + * + * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; + * }); + * // => true + */ + function isEqual(a, b, callback, thisArg, stackA, stackB) { + // used to indicate that when comparing objects, `a` has at least the properties of `b` + var whereIndicator = callback === indicatorObject; + if (callback && !whereIndicator) { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2); + var result = callback(a, b); + if (typeof result != 'undefined') { + return !!result; + } + } + // exit early for identical values + if (a === b) { + // treat `+0` vs. `-0` as not equal + return a !== 0 || (1 / a == 1 / b); + } + var type = typeof a, + otherType = typeof b; + + // exit early for unlike primitive values + if (a === a && + (!a || (type != 'function' && type != 'object')) && + (!b || (otherType != 'function' && otherType != 'object'))) { + return false; + } + // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior + // http://es5.github.com/#x15.3.4.4 + if (a == null || b == null) { + return a === b; + } + // compare [[Class]] names + var className = toString.call(a), + otherClass = toString.call(b); + + if (className == argsClass) { + className = objectClass; + } + if (otherClass == argsClass) { + otherClass = objectClass; + } + if (className != otherClass) { + return false; + } + switch (className) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal + return +a == +b; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return a != +a + ? b != +b + // but treat `+0` vs. `-0` as not equal + : (a == 0 ? (1 / a == 1 / b) : a == +b); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.com/#x15.10.6.4) + // treat string primitives and their corresponding object instances as equal + return a == b + ''; + } + var isArr = className == arrayClass; + if (!isArr) { + // unwrap any `lodash` wrapped values + if (a.__wrapped__ || b.__wrapped__) { + return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB); + } + // exit for functions and DOM nodes + if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) { + return false; + } + // in older versions of Opera, `arguments` objects have `Array` constructors + var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor, + ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor; + + // non `Object` object instances with different constructors are not equal + if (ctorA != ctorB && !( + isFunction(ctorA) && ctorA instanceof ctorA && + isFunction(ctorB) && ctorB instanceof ctorB + )) { + return false; + } + } + // assume cyclic structures are equal + // the algorithm for detecting cyclic structures is adapted from ES 5.1 + // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3) + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == a) { + return stackB[length] == b; + } + } + var size = 0; + result = true; + + // add `a` and `b` to the stack of traversed objects + stackA.push(a); + stackB.push(b); + + // recursively compare objects and arrays (susceptible to call stack limits) + if (isArr) { + length = a.length; + size = b.length; + + // compare lengths to determine if a deep comparison is necessary + result = size == a.length; + if (!result && !whereIndicator) { + return result; + } + // deep compare the contents, ignoring non-numeric properties + while (size--) { + var index = length, + value = b[size]; + + if (whereIndicator) { + while (index--) { + if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) { + break; + } + } + } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) { + break; + } + } + return result; + } + // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` + // which, in this case, is more costly + forIn(b, function(value, key, b) { + if (hasOwnProperty.call(b, key)) { + // count the number of properties. + size++; + // deep compare each property value. + return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB)); + } + }); + + if (result && !whereIndicator) { + // ensure both objects have the same number of properties + forIn(a, function(value, key, a) { + if (hasOwnProperty.call(a, key)) { + // `size` will be `-1` if `a` has more properties than `b` + return (result = --size > -1); + } + }); + } + return result; + } + + /** + * Checks if `value` is, or can be coerced to, a finite number. + * + * Note: This is not the same as native `isFinite`, which will return true for + * booleans and empty strings. See http://es5.github.com/#x15.1.2.5. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`. + * @example + * + * _.isFinite(-101); + * // => true + * + * _.isFinite('10'); + * // => true + * + * _.isFinite(true); + * // => false + * + * _.isFinite(''); + * // => false + * + * _.isFinite(Infinity); + * // => false + */ + function isFinite(value) { + return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + } + + /** + * Checks if `value` is a function. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + */ + function isFunction(value) { + return typeof value == 'function'; + } + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return value instanceof Function || toString.call(value) == funcClass; + }; + } + + /** + * Checks if `value` is the language type of Object. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ + function isObject(value) { + // check if the value is the ECMAScript language type of Object + // http://es5.github.com/#x8 + // and avoid a V8 bug + // http://code.google.com/p/v8/issues/detail?id=2291 + return value ? objectTypes[typeof value] : false; + } + + /** + * Checks if `value` is `NaN`. + * + * Note: This is not the same as native `isNaN`, which will return `true` for + * `undefined` and other values. See http://es5.github.com/#x15.1.2.4. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // `NaN` as a primitive is the only value that is not equal to itself + // (perform the [[Class]] check first to avoid errors with some host objects in IE) + return isNumber(value) && value != +value + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(undefined); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is a number. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`. + * @example + * + * _.isNumber(8.4 * 5); + * // => true + */ + function isNumber(value) { + return typeof value == 'number' || toString.call(value) == numberClass; + } + + /** + * Checks if a given `value` is an object created by the `Object` constructor. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + * @example + * + * function Stooge(name, age) { + * this.name = name; + * this.age = age; + * } + * + * _.isPlainObject(new Stooge('moe', 40)); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'name': 'moe', 'age': 40 }); + * // => true + */ + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && typeof value == 'object')) { + return false; + } + var valueOf = value.valueOf, + objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value)) + : shimIsPlainObject(value); + }; + + /** + * Checks if `value` is a regular expression. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`. + * @example + * + * _.isRegExp(/moe/); + * // => true + */ + function isRegExp(value) { + return value instanceof RegExp || toString.call(value) == regexpClass; + } + + /** + * Checks if `value` is a string. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`. + * @example + * + * _.isString('moe'); + * // => true + */ + function isString(value) { + return typeof value == 'string' || toString.call(value) == stringClass; + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + */ + function isUndefined(value) { + return typeof value == 'undefined'; + } + + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined`, into the destination object. Subsequent sources + * will overwrite propery assignments of previous sources. If a `callback` function + * is passed, it will be executed to produce the merged values of the destination + * and source properties. If `callback` returns `undefined`, merging will be + * handled by the method instead. The `callback` is bound to `thisArg` and + * invoked with two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize merging properties. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [deepIndicator] Internally used to indicate that `stackA` + * and `stackB` are arrays of traversed objects instead of source objects. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate values with their + * source counterparts. + * @returns {Object} Returns the destination object. + * @example + * + * var names = { + * 'stooges': [ + * { 'name': 'moe' }, + * { 'name': 'larry' } + * ] + * }; + * + * var ages = { + * 'stooges': [ + * { 'age': 40 }, + * { 'age': 50 } + * ] + * }; + * + * _.merge(names, ages); + * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] } + * + * var food = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var otherFood = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(food, otherFood, function(a, b) { + * return _.isArray(a) ? a.concat(b) : undefined; + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + */ + function merge(object, source, deepIndicator) { + var args = arguments, + index = 0, + length = 2; + + if (!isObject(object)) { + return object; + } + if (deepIndicator === indicatorObject) { + var callback = args[3], + stackA = args[4], + stackB = args[5]; + } else { + stackA = []; + stackB = []; + + // allows working with `_.reduce` and `_.reduceRight` without + // using their `callback` arguments, `index|key` and `collection` + if (typeof deepIndicator != 'number') { + length = args.length; + } + if (length > 3 && typeof args[length - 2] == 'function') { + callback = createCallback(args[--length - 1], args[length--], 2); + } else if (length > 2 && typeof args[length - 1] == 'function') { + callback = args[--length]; + } + } + while (++index < length) { + (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) { + var found, + isArr, + result = source, + value = object[key]; + + if (source && ((isArr = isArray(source)) || isPlainObject(source))) { + // avoid merging previously merged cyclic sources + var stackLength = stackA.length; + while (stackLength--) { + if ((found = stackA[stackLength] == source)) { + value = stackB[stackLength]; + break; + } + } + if (!found) { + value = isArr + ? (isArray(value) ? value : []) + : (isPlainObject(value) ? value : {}); + + if (callback) { + result = callback(value, source); + if (typeof result != 'undefined') { + value = result; + } + } + // add `source` and associated `value` to the stack of traversed objects + stackA.push(source); + stackB.push(value); + + // recursively merge objects and arrays (susceptible to call stack limits) + if (!callback) { + value = merge(value, source, indicatorObject, callback, stackA, stackB); + } + } + } + else { + if (callback) { + result = callback(value, source); + if (typeof result == 'undefined') { + result = source; + } + } + if (typeof result != 'undefined') { + value = result; + } + } + object[key] = value; + }); + } + return object; + } + + /** + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a `callback` function is passed, it will be executed + * for each property in the `object`, omitting the properties `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit + * or the function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. + * @example + * + * _.omit({ 'name': 'moe', 'age': 40 }, 'age'); + * // => { 'name': 'moe' } + * + * _.omit({ 'name': 'moe', 'age': 40 }, function(value) { + * return typeof value == 'number'; + * }); + * // => { 'name': 'moe' } + */ + function omit(object, callback, thisArg) { + var isFunc = typeof callback == 'function', + result = {}; + + if (isFunc) { + callback = createCallback(callback, thisArg); + } else { + var props = concat.apply(arrayRef, arguments); + } + forIn(object, function(value, key, object) { + if (isFunc + ? !callback(value, key, object) + : indexOf(props, key, 1) < 0 + ) { + result[key] = value; + } + }); + return result; + } + + /** + * Creates a two dimensional array of the given object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. + * @example + * + * _.pairs({ 'moe': 30, 'larry': 40 }); + * // => [['moe', 30], ['larry', 40]] (order is not guaranteed) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of property + * names. If `callback` is passed, it will be executed for each property in the + * `object`, picking the properties `callback` returns truthy for. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called + * per iteration or properties to pick, either as individual arguments or arrays. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name'); + * // => { 'name': 'moe' } + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'moe' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = 0, + props = concat.apply(arrayRef, arguments), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = createCallback(callback, thisArg); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * Creates an array composed of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property values. + * @example + * + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] + */ + function values(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array of elements from the specified indexes, or keys, of the + * `collection`. Indexes may be specified as individual arguments or as arrays + * of indexes. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Array|Number|String} [index1, index2, ...] The indexes of + * `collection` to retrieve, either as individual arguments or arrays. + * @returns {Array} Returns a new array of elements corresponding to the + * provided indexes. + * @example + * + * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); + * // => ['a', 'c', 'e'] + * + * _.at(['moe', 'larry', 'curly'], 0, 2); + * // => ['moe', 'curly'] + */ + function at(collection) { + var index = -1, + props = concat.apply(arrayRef, slice(arguments, 1)), + length = props.length, + result = Array(length); + + if (noCharByIndex && isString(collection)) { + collection = collection.split(''); + } + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + + /** + * Checks if a given `target` element is present in a `collection` using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @alias include + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Mixed} target The value to check for. + * @param {Number} [fromIndex=0] The index to search from. + * @returns {Boolean} Returns `true` if the `target` element is found, else `false`. + * @example + * + * _.contains([1, 2, 3], 1); + * // => true + * + * _.contains([1, 2, 3], 1, 2); + * // => false + * + * _.contains({ 'name': 'moe', 'age': 40 }, 'moe'); + * // => true + * + * _.contains('curly', 'ur'); + * // => true + */ + function contains(collection, target, fromIndex) { + var index = -1, + length = collection ? collection.length : 0, + result = false; + + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; + if (typeof length == 'number') { + result = (isString(collection) + ? collection.indexOf(target, fromIndex) + : indexOf(collection, target, fromIndex) + ) > -1; + } else { + each(collection, function(value) { + if (++index >= fromIndex) { + return !(result = value === target); + } + }); + } + return result; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the given `callback`. The corresponding value of each key + * is the number of times the key was returned by the `callback`. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': 1, '6': 2 } + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + function countBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); + }); + return result; + } + + /** + * Checks if the `callback` returns a truthy value for **all** elements of a + * `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias all + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if all elements pass the callback check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.every(stooges, 'age'); + * // => true + * + * // using "_.where" callback shorthand + * _.every(stooges, { 'age': 50 }); + * // => false + */ + function every(collection, callback, thisArg) { + var result = true; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (!(result = !!callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return (result = !!callback(value, index, collection)); + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * the `callback` returns truthy for. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias select + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that passed the callback check. + * @example + * + * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [2, 4, 6] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.filter(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + * + * // using "_.where" callback shorthand + * _.filter(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + */ + function filter(collection, callback, thisArg) { + var result = []; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (callback(value, index, collection)) { + result.push(value); + } + } + } else { + each(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result.push(value); + } + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning the first that the `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias detect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the element that passed the callback check, + * else `undefined`. + * @example + * + * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => 2 + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'banana', 'organic': true, 'type': 'fruit' }, + * { 'name': 'beet', 'organic': false, 'type': 'vegetable' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * var veggie = _.find(food, { 'type': 'vegetable' }); + * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' } + * + * // using "_.pluck" callback shorthand + * var healthy = _.find(food, 'organic'); + * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' } + */ + function find(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; + } + + /** + * Iterates over a `collection`, executing the `callback` for each element in + * the `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). Callbacks may exit iteration early + * by explicitly returning `false`. + * + * @static + * @memberOf _ + * @alias each + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + * @example + * + * _([1, 2, 3]).forEach(alert).join(','); + * // => alerts each number and returns '1,2,3' + * + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert); + * // => alerts each number value (order is not guaranteed) + */ + function forEach(collection, callback, thisArg) { + if (callback && typeof thisArg == 'undefined' && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (callback(collection[index], index, collection) === false) { + break; + } + } + } else { + each(collection, callback, thisArg); + } + return collection; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the `callback`. The corresponding value of each key is + * an array of elements passed to `callback` that returned the key. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false` + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * // using "_.pluck" callback shorthand + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + function groupBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); + }); + return result; + } + + /** + * Invokes the method named by `methodName` on each element in the `collection`, + * returning an array of the results of each invoked method. Additional arguments + * will be passed to each invoked method. If `methodName` is a function, it will + * be invoked for, and `this` bound to, each element in the `collection`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} Returns a new array of the results of each invoked method. + * @example + * + * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invoke([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + function invoke(collection, methodName) { + var args = slice(arguments, 2), + index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); + }); + return result; + } + + /** + * Creates an array of values by running each element in the `collection` + * through the `callback`. The `callback` is bound to `thisArg` and invoked with + * three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias collect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of the results of each `callback` execution. + * @example + * + * _.map([1, 2, 3], function(num) { return num * 3; }); + * // => [3, 6, 9] + * + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * // => [3, 6, 9] (order is not guaranteed) + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.map(stooges, 'name'); + * // => ['moe', 'larry'] + */ + function map(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + if (isArray(collection)) { + while (++index < length) { + result[index] = callback(collection[index], index, collection); + } + } else { + each(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); + } + return result; + } + + /** + * Retrieves the maximum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.max(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'larry', 'age': 50 }; + * + * // using "_.pluck" callback shorthand + * _.max(stooges, 'age'); + * // => { 'name': 'larry', 'age': 50 }; + */ + function max(collection, callback, thisArg) { + var computed = -Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value > result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current > computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the minimum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.min(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'moe', 'age': 40 }; + * + * // using "_.pluck" callback shorthand + * _.min(stooges, 'age'); + * // => { 'name': 'moe', 'age': 40 }; + */ + function min(collection, callback, thisArg) { + var computed = Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value < result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current < computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the value of a specified property from all elements in the `collection`. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {String} property The property to pluck. + * @returns {Array} Returns a new array of property values. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.pluck(stooges, 'name'); + * // => ['moe', 'larry'] + */ + var pluck = map; + + /** + * Reduces a `collection` to a value that is the accumulated result of running + * each element in the `collection` through the `callback`, where each successive + * `callback` execution consumes the return value of the previous execution. + * If `accumulator` is not passed, the first element of the `collection` will be + * used as the initial `accumulator` value. The `callback` is bound to `thisArg` + * and invoked with four arguments; (accumulator, value, index|key, collection). + * + * @static + * @memberOf _ + * @alias foldl, inject + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var sum = _.reduce([1, 2, 3], function(sum, num) { + * return sum + num; + * }); + * // => 6 + * + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * return result; + * }, {}); + * // => { 'a': 3, 'b': 6, 'c': 9 } + */ + function reduce(collection, callback, accumulator, thisArg) { + var noaccum = arguments.length < 3; + callback = createCallback(callback, thisArg, 4); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + if (noaccum) { + accumulator = collection[++index]; + } + while (++index < length) { + accumulator = callback(accumulator, collection[index], index, collection); + } + } else { + each(collection, function(value, index, collection) { + accumulator = noaccum + ? (noaccum = false, value) + : callback(accumulator, value, index, collection) + }); + } + return accumulator; + } + + /** + * This method is similar to `_.reduce`, except that it iterates over a + * `collection` from right to left. + * + * @static + * @memberOf _ + * @alias foldr + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var list = [[0, 1], [2, 3], [4, 5]]; + * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, callback, accumulator, thisArg) { + var iterable = collection, + length = collection ? collection.length : 0, + noaccum = arguments.length < 3; + + if (typeof length != 'number') { + var props = keys(collection); + length = props.length; + } else if (noCharByIndex && isString(collection)) { + iterable = collection.split(''); + } + callback = createCallback(callback, thisArg, 4); + forEach(collection, function(value, index, collection) { + index = props ? props[--length] : --length; + accumulator = noaccum + ? (noaccum = false, iterable[index]) + : callback(accumulator, iterable[index], index, collection); + }); + return accumulator; + } + + /** + * The opposite of `_.filter`, this method returns the elements of a + * `collection` that `callback` does **not** return truthy for. + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that did **not** pass the + * callback check. + * @example + * + * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [1, 3, 5] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.reject(food, 'organic'); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + * + * // using "_.where" callback shorthand + * _.reject(food, { 'type': 'fruit' }); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + */ + function reject(collection, callback, thisArg) { + callback = createCallback(callback, thisArg); + return filter(collection, function(value, index, collection) { + return !callback(value, index, collection); + }); + } + + /** + * Creates an array of shuffled `array` values, using a version of the + * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to shuffle. + * @returns {Array} Returns a new shuffled collection. + * @example + * + * _.shuffle([1, 2, 3, 4, 5, 6]); + * // => [4, 1, 6, 3, 5, 2] + */ + function shuffle(collection) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + var rand = floor(nativeRandom() * (++index + 1)); + result[index] = result[rand]; + result[rand] = value; + }); + return result; + } + + /** + * Gets the size of the `collection` by returning `collection.length` for arrays + * and array-like objects or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to inspect. + * @returns {Number} Returns `collection.length` or number of own enumerable properties. + * @example + * + * _.size([1, 2]); + * // => 2 + * + * _.size({ 'one': 1, 'two': 2, 'three': 3 }); + * // => 3 + * + * _.size('curly'); + * // => 5 + */ + function size(collection) { + var length = collection ? collection.length : 0; + return typeof length == 'number' ? length : keys(collection).length; + } + + /** + * Checks if the `callback` returns a truthy value for **any** element of a + * `collection`. The function returns as soon as it finds passing value, and + * does not iterate over the entire `collection`. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias any + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if any element passes the callback check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.some(food, 'organic'); + * // => true + * + * // using "_.where" callback shorthand + * _.some(food, { 'type': 'meat' }); + * // => false + */ + function some(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if ((result = callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return !(result = callback(value, index, collection)); + }); + } + return !!result; + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in the `collection` through the `callback`. This method + * performs a stable sort, that is, it will preserve the original sort order of + * equal elements. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of sorted elements. + * @example + * + * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * // => [3, 1, 2] + * + * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * // => [3, 1, 2] + * + * // using "_.pluck" callback shorthand + * _.sortBy(['banana', 'strawberry', 'apple'], 'length'); + * // => ['apple', 'banana', 'strawberry'] + */ + function sortBy(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + forEach(collection, function(value, key, collection) { + result[++index] = { + 'criteria': callback(value, key, collection), + 'index': index, + 'value': value + }; + }); + + length = result.length; + result.sort(compareAscending); + while (length--) { + result[length] = result[length].value; + } + return result; + } + + /** + * Converts the `collection` to an array. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to convert. + * @returns {Array} Returns the new converted array. + * @example + * + * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); + * // => [2, 3, 4] + */ + function toArray(collection) { + if (collection && typeof collection.length == 'number') { + return noCharByIndex && isString(collection) + ? collection.split('') + : slice(collection); + } + return values(collection); + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * that have the given `properties`. When checking `properties`, this method + * performs a deep comparison between values to determine if they are equivalent + * to each other. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Object} properties The object of property values to filter by. + * @returns {Array} Returns a new array of elements that have the given `properties`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.where(stooges, { 'age': 40 }); + * // => [{ 'name': 'moe', 'age': 40 }] + */ + var where = filter; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values of `array` removed. The values + * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result.push(value); + } + } + return result; + } + + /** + * Creates an array of `array` elements not present in the other arrays + * using strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {Array} [array1, array2, ...] Arrays to check. + * @returns {Array} Returns a new array of `array` elements not present in the + * other arrays. + * @example + * + * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); + * // => [1, 3, 4] + */ + function difference(array) { + var index = -1, + length = array ? array.length : 0, + flattened = concat.apply(arrayRef, arguments), + contains = cachedContains(flattened, length), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Gets the first element of the `array`. If a number `n` is passed, the first + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the first elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias head, take + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the first element(s) of `array`. + * @example + * + * _.first([1, 2, 3]); + * // => 1 + * + * _.first([1, 2, 3], 2); + * // => [1, 2] + * + * _.first([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [1, 2] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.first(food, 'organic'); + * // => [{ 'name': 'banana', 'organic': true }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.first(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }] + */ + function first(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = -1; + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[0]; + } + } + return slice(array, 0, nativeMin(nativeMax(0, n), length)); + } + } + + /** + * Flattens a nested array (the nesting can be to any depth). If `shallow` is + * truthy, `array` will only be flattened a single level. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @param {Boolean} shallow A flag to indicate only flattening a single level. + * @returns {Array} Returns a new flattened array. + * @example + * + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; + * + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, [[4]]]; + */ + function flatten(array, shallow) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + + // recursively flatten arrays (susceptible to call stack limits) + if (isArray(value)) { + push.apply(result, shallow ? value : flatten(value)); + } else { + result.push(value); + } + } + return result; + } + + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If the `array` is already + * sorted, passing `true` for `fromIndex` will run a faster binary search. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to + * perform a binary search on a sorted `array`. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 + * + * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); + * // => 2 + */ + function indexOf(array, value, fromIndex) { + var index = -1, + length = array ? array.length : 0; + + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1; + } else if (fromIndex) { + index = sortedIndex(array, value); + return array[index] === value ? index : -1; + } + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Gets all but the last element of `array`. If a number `n` is passed, the + * last `n` elements are excluded from the result. If a `callback` function + * is passed, the last elements the `callback` returns truthy for are excluded + * from the result. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + * + * _.initial([1, 2, 3], 2); + * // => [1] + * + * _.initial([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [1] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.initial(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.initial(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'banana', 'type': 'fruit' }] + */ + function initial(array, callback, thisArg) { + if (!array) { + return []; + } + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : callback || n; + } + return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); + } + + /** + * Computes the intersection of all the passed-in arrays using strict equality + * for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique elements that are present + * in **all** of the arrays. + * @example + * + * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2] + */ + function intersection(array) { + var args = arguments, + argsLength = args.length, + cache = { '0': {} }, + index = -1, + length = array ? array.length : 0, + isLarge = length >= 100, + result = [], + seen = result; + + outer: + while (++index < length) { + var value = array[index]; + if (isLarge) { + var key = value + ''; + var inited = hasOwnProperty.call(cache[0], key) + ? !(seen = cache[0][key]) + : (seen = cache[0][key] = []); + } + if (inited || indexOf(seen, value) < 0) { + if (isLarge) { + seen.push(value); + } + var argsIndex = argsLength; + while (--argsIndex) { + if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) { + continue outer; + } + } + result.push(value); + } + } + return result; + } + + /** + * Gets the last element of the `array`. If a number `n` is passed, the last + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the last elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the last element(s) of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + * + * _.last([1, 2, 3], 2); + * // => [2, 3] + * + * _.last([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.last(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.last(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }] + */ + function last(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[length - 1]; + } + } + return slice(array, nativeMax(0, length - n)); + } + } + + /** + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=array.length-1] The index to search from. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var index = array ? array.length : 0; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Creates an object composed from arrays of `keys` and `values`. Pass either + * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or + * two arrays, one of `keys` and one of corresponding `values`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} keys The array of keys. + * @param {Array} [values=[]] The array of values. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. + * @example + * + * _.object(['moe', 'larry'], [30, 40]); + * // => { 'moe': 30, 'larry': 40 } + */ + function object(keys, values) { + var index = -1, + length = keys ? keys.length : 0, + result = {}; + + while (++index < length) { + var key = keys[index]; + if (values) { + result[key] = values[index]; + } else { + result[key[0]] = key[1]; + } + } + return result; + } + + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Number} [start=0] The start of the range. + * @param {Number} end The end of the range. + * @param {Number} [step=1] The value to increment or descrement by. + * @returns {Array} Returns a new range array. + * @example + * + * _.range(10); + * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * + * _.range(1, 11); + * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + * + * _.range(0, 30, 5); + * // => [0, 5, 10, 15, 20, 25] + * + * _.range(0, -10, -1); + * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = +step || 1; + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so V8 will avoid the slower "dictionary" mode + // http://youtu.be/XAqIpGU8ZZk#t=17m25s + var index = -1, + length = nativeMax(0, ceil((end - start) / step)), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * The opposite of `_.initial`, this method gets all but the first value of `array`. + * If a number `n` is passed, the first `n` values are excluded from the result. + * If a `callback` function is passed, the first elements the `callback` returns + * truthy for are excluded from the result. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias drop, tail + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.rest([1, 2, 3]); + * // => [2, 3] + * + * _.rest([1, 2, 3], 2); + * // => [3] + * + * _.rest([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.rest(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.rest(food, { 'type': 'fruit' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }] + */ + function rest(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { + var n = 0, + index = -1, + length = array ? array.length : 0; + + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); + } + return slice(array, n); + } + + /** + * Uses a binary search to determine the smallest index at which the `value` + * should be inserted into `array` in order to maintain the sort order of the + * sorted `array`. If `callback` is passed, it will be executed for `value` and + * each element in `array` to compute their sort ranking. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to iterate over. + * @param {Mixed} value The value to evaluate. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Number} Returns the index at which the value should be inserted + * into `array`. + * @example + * + * _.sortedIndex([20, 30, 50], 40); + * // => 2 + * + * // using "_.pluck" callback shorthand + * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 2 + * + * var dict = { + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * }; + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return dict.wordToNumber[word]; + * }); + * // => 2 + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return this.wordToNumber[word]; + * }, dict); + * // => 2 + */ + function sortedIndex(array, value, callback, thisArg) { + var low = 0, + high = array ? array.length : low; + + // explicitly reference `identity` for better inlining in Firefox + callback = callback ? createCallback(callback, thisArg, 1) : identity; + value = callback(value); + + while (low < high) { + var mid = (low + high) >>> 1; + callback(array[mid]) < value + ? low = mid + 1 + : high = mid; + } + return low; + } + + /** + * Computes the union of the passed-in arrays using strict equality for + * comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique values, in order, that are + * present in one or more of the arrays. + * @example + * + * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2, 3, 101, 10] + */ + function union() { + return uniq(concat.apply(arrayRef, arguments)); + } + + /** + * Creates a duplicate-value-free version of the `array` using strict equality + * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` + * for `isSorted` will run a faster algorithm. If `callback` is passed, each + * element of `array` is passed through a callback` before uniqueness is computed. + * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias unique + * @category Arrays + * @param {Array} array The array to process. + * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a duplicate-value-free array. + * @example + * + * _.uniq([1, 2, 1, 3, 1]); + * // => [1, 2, 3] + * + * _.uniq([1, 1, 2, 2, 3], true); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); }); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math); + * // => [1, 2, 3] + * + * // using "_.pluck" callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniq(array, isSorted, callback, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = [], + seen = result; + + // juggle arguments + if (typeof isSorted == 'function') { + thisArg = callback; + callback = isSorted; + isSorted = false; + } + // init value cache for large arrays + var isLarge = !isSorted && length >= 75; + if (isLarge) { + var cache = {}; + } + if (callback) { + seen = []; + callback = createCallback(callback, thisArg); + } + while (++index < length) { + var value = array[index], + computed = callback ? callback(value, index, array) : value; + + if (isLarge) { + var key = computed + ''; + var inited = hasOwnProperty.call(cache, key) + ? !(seen = cache[key]) + : (seen = cache[key] = []); + } + if (isSorted + ? !index || seen[seen.length - 1] !== computed + : inited || indexOf(seen, computed) < 0 + ) { + if (callback || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * Creates an array with all occurrences of the passed values removed using + * strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to filter. + * @param {Mixed} [value1, value2, ...] Values to remove. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] + */ + function without(array) { + var index = -1, + length = array ? array.length : 0, + contains = cachedContains(arguments, 1), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Groups the elements of each array at their corresponding indexes. Useful for + * separate data sources that are coordinated through matching array indexes. + * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix + * in a similar fashion. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of grouped elements. + * @example + * + * _.zip(['moe', 'larry'], [30, 40], [true, false]); + * // => [['moe', 30, true], ['larry', 40, false]] + */ + function zip(array) { + var index = -1, + length = array ? max(pluck(arguments, 'length')) : 0, + result = Array(length); + + while (++index < length) { + result[index] = pluck(arguments, index); + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function that is restricted to executing `func` only after it is + * called `n` times. The `func` is executed with the `this` binding of the + * created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Number} n The number of times the function must be called before + * it is executed. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var renderNotes = _.after(notes.length, render); + * _.forEach(notes, function(note) { + * note.asyncSave({ 'success': renderNotes }); + * }); + * // `renderNotes` is run once, after all notes have saved + */ + function after(n, func) { + if (n < 1) { + return func(); + } + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * passed to the bound function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to bind. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var func = function(greeting) { + * return greeting + ' ' + this.name; + * }; + * + * func = _.bind(func, { 'name': 'moe' }, 'hi'); + * func(); + * // => 'hi moe' + */ + function bind(func, thisArg) { + // use `Function#bind` if it exists and is fast + // (in V8 `Function#bind` is slower except when partially applied) + return isBindFast || (nativeBind && arguments.length > 2) + ? nativeBind.call.apply(nativeBind, arguments) + : createBound(func, thisArg, slice(arguments, 2)); + } + + /** + * Binds methods on `object` to `object`, overwriting the existing method. + * Method names may be specified as individual arguments or as arrays of method + * names. If no method names are provided, all the function properties of `object` + * will be bound. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object to bind and assign the bound methods to. + * @param {String} [methodName1, methodName2, ...] Method names on the object to bind. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'onClick': function() { alert('clicked ' + this.label); } + * }; + * + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => alerts 'clicked docs', when the button is clicked + */ + function bindAll(object) { + var funcs = concat.apply(arrayRef, arguments), + index = funcs.length > 1 ? 0 : (funcs = functions(object), -1), + length = funcs.length; + + while (++index < length) { + var key = funcs[index]; + object[key] = bind(object[key], object); + } + return object; + } + + /** + * Creates a function that, when called, invokes the method at `object[key]` + * and prepends any additional `bindKey` arguments to those passed to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. + * See http://michaux.ca/articles/lazy-function-definition-pattern. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object the method belongs to. + * @param {String} key The key of the method. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'name': 'moe', + * 'greet': function(greeting) { + * return greeting + ' ' + this.name; + * } + * }; + * + * var func = _.bindKey(object, 'greet', 'hi'); + * func(); + * // => 'hi moe' + * + * object.greet = function(greeting) { + * return greeting + ', ' + this.name + '!'; + * }; + * + * func(); + * // => 'hi, moe!' + */ + function bindKey(object, key) { + return createBound(object, key, slice(arguments, 2)); + } + + /** + * Creates a function that is the composition of the passed functions, + * where each function consumes the return value of the function that follows. + * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * Each function is executed with the `this` binding of the composed function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} [func1, func2, ...] Functions to compose. + * @returns {Function} Returns the new composed function. + * @example + * + * var greet = function(name) { return 'hi ' + name; }; + * var exclaim = function(statement) { return statement + '!'; }; + * var welcome = _.compose(exclaim, greet); + * welcome('moe'); + * // => 'hi moe!' + */ + function compose() { + var funcs = arguments; + return function() { + var args = arguments, + length = funcs.length; + + while (length--) { + args = [funcs[length].apply(this, args)]; + } + return args[0]; + }; + } + + /** + * Creates a function that will delay the execution of `func` until after + * `wait` milliseconds have elapsed since the last time it was invoked. Pass + * `true` for `immediate` to cause debounce to invoke `func` on the leading, + * instead of the trailing, edge of the `wait` timeout. Subsequent calls to + * the debounced function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to debounce. + * @param {Number} wait The number of milliseconds to delay. + * @param {Boolean} immediate A flag to indicate execution is on the leading + * edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * var lazyLayout = _.debounce(calculateLayout, 300); + * jQuery(window).on('resize', lazyLayout); + */ + function debounce(func, wait, immediate) { + var args, + result, + thisArg, + timeoutId; + + function delayed() { + timeoutId = null; + if (!immediate) { + result = func.apply(thisArg, args); + } + } + return function() { + var isImmediate = immediate && !timeoutId; + args = arguments; + thisArg = this; + + clearTimeout(timeoutId); + timeoutId = setTimeout(delayed, wait); + + if (isImmediate) { + result = func.apply(thisArg, args); + } + return result; + }; + } + + /** + * Executes the `func` function after `wait` milliseconds. Additional arguments + * will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to delay. + * @param {Number} wait The number of milliseconds to delay execution. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * var log = _.bind(console.log, console); + * _.delay(log, 1000, 'logged later'); + * // => 'logged later' (Appears after one second.) + */ + function delay(func, wait) { + var args = slice(arguments, 2); + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * Defers executing the `func` function until the current call stack has cleared. + * Additional arguments will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to defer. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * _.defer(function() { alert('deferred'); }); + * // returns from the function before `alert` is called + */ + function defer(func) { + var args = slice(arguments, 1); + return setTimeout(function() { func.apply(undefined, args); }, 1); + } + // use `setImmediate` if it's available in Node.js + if (isV8 && freeModule && typeof setImmediate == 'function') { + defer = bind(setImmediate, window); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * passed, it will be used to determine the cache key for storing the result + * based on the arguments passed to the memoized function. By default, the first + * argument passed to the memoized function is used as the cache key. The `func` + * is executed with the `this` binding of the memoized function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] A function used to resolve the cache key. + * @returns {Function} Returns the new memoizing function. + * @example + * + * var fibonacci = _.memoize(function(n) { + * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * }); + */ + function memoize(func, resolver) { + var cache = {}; + return function() { + var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + ''; + return hasOwnProperty.call(cache, key) + ? cache[key] + : (cache[key] = func.apply(this, arguments)); + }; + } + + /** + * Creates a function that is restricted to execute `func` once. Repeat calls to + * the function will return the value of the first call. The `func` is executed + * with the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` executes `createApplication` once + */ + function once(func) { + var ran, + result; + + return function() { + if (ran) { + return result; + } + ran = true; + result = func.apply(this, arguments); + + // clear the `func` variable so the function may be garbage collected + func = null; + return result; + }; + } + + /** + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those passed to the new function. This + * method is similar to `_.bind`, except it does **not** alter the `this` binding. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var hi = _.partial(greet, 'hi'); + * hi('moe'); + * // => 'hi moe' + */ + function partial(func) { + return createBound(func, slice(arguments, 1)); + } + + /** + * This method is similar to `_.partial`, except that `partial` arguments are + * appended to those passed to the new function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var defaultsDeep = _.partialRight(_.merge, _.defaults); + * + * var options = { + * 'variable': 'data', + * 'imports': { 'jq': $ } + * }; + * + * defaultsDeep(options, _.templateSettings); + * + * options.variable + * // => 'data' + * + * options.imports + * // => { '_': _, 'jq': $ } + */ + function partialRight(func) { + return createBound(func, slice(arguments, 1), null, indicatorObject); + } + + /** + * Creates a function that, when executed, will only call the `func` + * function at most once per every `wait` milliseconds. If the throttled + * function is invoked more than once during the `wait` timeout, `func` will + * also be called on the trailing edge of the timeout. Subsequent calls to the + * throttled function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to throttle. + * @param {Number} wait The number of milliseconds to throttle executions to. + * @returns {Function} Returns the new throttled function. + * @example + * + * var throttled = _.throttle(updatePosition, 100); + * jQuery(window).on('scroll', throttled); + */ + function throttle(func, wait) { + var args, + result, + thisArg, + timeoutId, + lastCalled = 0; + + function trailingCall() { + lastCalled = new Date; + timeoutId = null; + result = func.apply(thisArg, args); + } + return function() { + var now = new Date, + remaining = wait - (now - lastCalled); + + args = arguments; + thisArg = this; + + if (remaining <= 0) { + clearTimeout(timeoutId); + timeoutId = null; + lastCalled = now; + result = func.apply(thisArg, args); + } + else if (!timeoutId) { + timeoutId = setTimeout(trailingCall, remaining); + } + return result; + }; + } + + /** + * Creates a function that passes `value` to the `wrapper` function as its + * first argument. Additional arguments passed to the function are appended + * to those passed to the `wrapper` function. The `wrapper` is executed with + * the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Mixed} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var hello = function(name) { return 'hello ' + name; }; + * hello = _.wrap(hello, function(func) { + * return 'before, ' + func('moe') + ', after'; + * }); + * hello(); + * // => 'before, hello moe, after' + */ + function wrap(value, wrapper) { + return function() { + var args = [value]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their + * corresponding HTML entities. + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} string The string to escape. + * @returns {String} Returns the escaped string. + * @example + * + * _.escape('Moe, Larry & Curly'); + * // => 'Moe, Larry & Curly' + */ + function escape(string) { + return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * This function returns the first argument passed to it. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Mixed} value Any value. + * @returns {Mixed} Returns `value`. + * @example + * + * var moe = { 'name': 'moe' }; + * moe === _.identity(moe); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Adds functions properties of `object` to the `lodash` function and chainable + * wrapper. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object of function properties to add to `lodash`. + * @example + * + * _.mixin({ + * 'capitalize': function(string) { + * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + * } + * }); + * + * _.capitalize('moe'); + * // => 'Moe' + * + * _('moe').capitalize(); + * // => 'Moe' + */ + function mixin(object) { + forEach(functions(object), function(methodName) { + var func = lodash[methodName] = object[methodName]; + + lodash.prototype[methodName] = function() { + var args = [this.__wrapped__]; + push.apply(args, arguments); + return new lodash(func.apply(lodash, args)); + }; + }); + } + + /** + * Reverts the '_' variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Utilities + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + window._ = oldDash; + return this; + } + + /** + * Produces a random number between `min` and `max` (inclusive). If only one + * argument is passed, a number between `0` and the given number will be returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Number} [min=0] The minimum possible value. + * @param {Number} [max=1] The maximum possible value. + * @returns {Number} Returns a random number. + * @example + * + * _.random(0, 5); + * // => a number between 0 and 5 + * + * _.random(5); + * // => also a number between 0 and 5 + */ + function random(min, max) { + if (min == null && max == null) { + max = 1; + } + min = +min || 0; + if (max == null) { + max = min; + min = 0; + } + return min + floor(nativeRandom() * ((+max || 0) - min + 1)); + } + + /** + * Resolves the value of `property` on `object`. If `property` is a function, + * it will be invoked and its result returned, else the property value is + * returned. If `object` is falsey, then `null` is returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object to inspect. + * @param {String} property The property to get the value of. + * @returns {Mixed} Returns the resolved value. + * @example + * + * var object = { + * 'cheese': 'crumpets', + * 'stuff': function() { + * return 'nonsense'; + * } + * }; + * + * _.result(object, 'cheese'); + * // => 'crumpets' + * + * _.result(object, 'stuff'); + * // => 'nonsense' + */ + function result(object, property) { + var value = object ? object[property] : undefined; + return isFunction(value) ? object[property]() : value; + } + + /** + * A micro-templating method that handles arbitrary delimiters, preserves + * whitespace, and correctly escapes quotes within interpolated code. + * + * Note: In the development build, `_.template` utilizes sourceURLs for easier + * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl + * + * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` + * build and using precompiled templates, or loading Lo-Dash in a sandbox. + * + * For more information on precompiling templates see: + * http://lodash.com/#custom-builds + * + * For more information on Chrome extension sandboxes see: + * http://developer.chrome.com/stable/extensions/sandboxingEval.html + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} text The template text. + * @param {Obect} data The data object used to populate the text. + * @param {Object} options The options object. + * escape - The "escape" delimiter regexp. + * evaluate - The "evaluate" delimiter regexp. + * interpolate - The "interpolate" delimiter regexp. + * sourceURL - The sourceURL of the template's compiled source. + * variable - The data object variable name. + * + * @returns {Function|String} Returns a compiled function when no `data` object + * is given, else it returns the interpolated text. + * @example + * + * // using a compiled template + * var compiled = _.template('hello <%= name %>'); + * compiled({ 'name': 'moe' }); + * // => 'hello moe' + * + * var list = '<% _.forEach(people, function(name) { %>
    • <%= name %>
    • <% }); %>'; + * _.template(list, { 'people': ['moe', 'larry'] }); + * // => '
    • moe
    • larry
    • ' + * + * // using the "escape" delimiter to escape HTML in data property values + * _.template('<%- value %>', { 'value': '\n```\n\nUsing [`npm`](http://npmjs.org/):\n\n```bash\nnpm install lodash\n\nnpm install -g lodash\nnpm link lodash\n```\n\nTo avoid potential issues, update `npm` before installing Lo-Dash:\n\n```bash\nnpm install npm -g\n```\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n\n// or as a drop-in replacement for Underscore\nvar _ = require('lodash/lodash.underscore');\n```\n\n**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it.\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n```js\nvar _ = require('lodash')._;\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire({\n 'paths': {\n 'underscore': 'path/to/lodash'\n }\n},\n['underscore'], function(_) {\n console.log(_.VERSION);\n});\n```\n\n## Release Notes\n\n### v1.0.1\n\n * Add support for specifying source map URLs in `-p`/`--source-map` build options\n * Ensured the second argument passed to `_.assign` is not treated as a `callback`\n * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`\n * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed\n * Made `_.defer` use `setImmediate`, in Node.js, when available\n * Made `_.where` search arrays for values regardless of their index position\n * Removed dead code from `_.template`\n\nThe full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog).\n\n## BestieJS\n\nLo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.\n\n## Author\n\n| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton \"Follow @jdalton on Twitter\") |\n|---|\n| [John-David Dalton](http://allyoucanleet.com/) |\n\n## Contributors\n\n| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz \"Follow @BlaineBublitz on Twitter\") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias \"Follow @mathias on Twitter\") |\n|---|---|---|\n| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) |\n", + "readmeFilename": "README.md", + "_id": "lodash@1.0.1", + "_from": "lodash@~1.0.1", + "scripts": {} +} diff --git a/node_modules/grunt/node_modules/findup-sync/package.json b/node_modules/grunt/node_modules/findup-sync/package.json new file mode 100644 index 000000000..95772f251 --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/package.json @@ -0,0 +1,48 @@ +{ + "name": "findup-sync", + "description": "Find the first file matching a given pattern in the current directory or the nearest ancestor directory.", + "version": "0.1.2", + "homepage": "https://github.com/cowboy/node-findup-sync", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/cowboy/node-findup-sync.git" + }, + "bugs": { + "url": "https://github.com/cowboy/node-findup-sync/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cowboy/node-findup-sync/blob/master/LICENSE-MIT" + } + ], + "main": "lib/findup-sync", + "engines": { + "node": ">= 0.6.0" + }, + "scripts": { + "test": "grunt nodeunit" + }, + "dependencies": { + "glob": "~3.1.21", + "lodash": "~1.0.1" + }, + "devDependencies": { + "grunt": "~0.4.0", + "grunt-contrib-jshint": "~0.2.0", + "grunt-contrib-nodeunit": "~0.1.2" + }, + "keywords": [ + "find", + "glob", + "file" + ], + "readme": "# findup-sync\n\nFind the first file matching a given pattern in the current directory or the nearest ancestor directory.\n\n## Getting Started\nInstall the module with: `npm install findup-sync`\n\n```js\nvar findup = require('findup-sync');\n\n// Start looking in the CWD.\nvar filepath1 = findup('{a,b}*.txt');\n\n// Start looking somewhere else, and ignore case (probably a good idea).\nvar filepath2 = findup('{a,b}*.txt', {cwd: '/some/path', nocase: true});\n```\n\n## Usage\n\n```js\nfindup(patternOrPatterns [, minimatchOptions])\n```\n\n### patternOrPatterns\nType: `String` or `Array` \nDefault: none\n\nOne or more wildcard glob patterns. Or just filenames.\n\n### minimatchOptions\nType: `Object` \nDefault: `{}`\n\nOptions to be passed to [minimatch](https://github.com/isaacs/minimatch).\n\nNote that if you want to start in a different directory than the current working directory, specify a `cwd` property here.\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\n\n## Release History\n2013-03-08 - v0.1.2 - Updated dependencies. Fixed a Node 0.9.x bug. Updated unit tests to work cross-platform. \n2012-11-15 - v0.1.1 - Now works without an options object. \n2012-11-01 - v0.1.0 - Initial release.\n", + "readmeFilename": "README.md", + "_id": "findup-sync@0.1.2", + "_from": "findup-sync@~0.1.0" +} diff --git a/node_modules/grunt/node_modules/findup-sync/test/findup-sync_test.js b/node_modules/grunt/node_modules/findup-sync/test/findup-sync_test.js new file mode 100644 index 000000000..f8baf9ef0 --- /dev/null +++ b/node_modules/grunt/node_modules/findup-sync/test/findup-sync_test.js @@ -0,0 +1,48 @@ +'use strict'; + +// Nodejs lib. +var path = require('path'); + +var findup = require('../lib/findup-sync.js'); + +// Get a relative path. +var rel = function(abspath) { + return typeof abspath === 'string' ? path.relative('.', abspath) : abspath; +}; + +exports['findup'] = { + setUp: function(done) { + this.cwd = process.cwd(); + done(); + }, + tearDown: function(done) { + process.chdir(this.cwd); + done(); + }, + 'simple': function(test) { + test.expect(8); + var opts = {cwd: 'test/fixtures/a/b'}; + test.equal(rel(findup('foo.txt', opts)), path.normalize('test/fixtures/a/foo.txt'), 'should find files'); + test.equal(rel(findup('bar.txt', opts)), path.normalize('test/fixtures/a/b/bar.txt'), 'should find files'); + test.equal(rel(findup('a.txt', opts)), path.normalize('test/fixtures/a.txt'), 'should find files'); + test.equal(rel(findup('?.txt', opts)), path.normalize('test/fixtures/a.txt'), 'should support glob patterns'); + test.equal(rel(findup('*.txt', opts)), path.normalize('test/fixtures/a/b/bar.txt'), 'should find the first thing that matches the glob pattern'); + test.equal(rel(findup(['b*.txt', 'f*.txt'], opts)), path.normalize('test/fixtures/a/b/bar.txt'), 'should find the first thing that matches any of the glob patterns'); + test.equal(rel(findup(['f*.txt', 'b*.txt'], opts)), path.normalize('test/fixtures/a/b/bar.txt'), 'should find the first thing that matches any of the glob patterns'); + test.equal(findup('not-gonna-exist-i-hope.txt', opts), null, 'should returning null if no files found'); + test.done(); + }, + 'cwd': function(test) { + test.expect(8); + process.chdir('test/fixtures/a/b'); + test.equal(rel(findup('foo.txt')), path.normalize('../foo.txt'), 'should find files'); + test.equal(rel(findup('bar.txt')), 'bar.txt', 'should find files'); + test.equal(rel(findup('a.txt')), path.normalize('../../a.txt'), 'should find files'); + test.equal(rel(findup('?.txt')), path.normalize('../../a.txt'), 'should support glob patterns'); + test.equal(rel(findup('*.txt')), 'bar.txt', 'should find the first thing that matches the glob pattern'); + test.equal(rel(findup(['b*.txt', 'f*.txt'])), 'bar.txt', 'should find the first thing that matches any of the glob patterns'); + test.equal(rel(findup(['f*.txt', 'b*.txt'])), 'bar.txt', 'should find the first thing that matches any of the glob patterns'); + test.equal(findup('not-gonna-exist-i-hope.txt'), null, 'should returning null if no files found'); + test.done(); + }, +}; diff --git a/node_modules/grunt/node_modules/findup-sync/test/fixtures/a.txt b/node_modules/grunt/node_modules/findup-sync/test/fixtures/a.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/findup-sync/test/fixtures/a/b/bar.txt b/node_modules/grunt/node_modules/findup-sync/test/fixtures/a/b/bar.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/findup-sync/test/fixtures/a/foo.txt b/node_modules/grunt/node_modules/findup-sync/test/fixtures/a/foo.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/findup-sync/test/fixtures/aaa.txt b/node_modules/grunt/node_modules/findup-sync/test/fixtures/aaa.txt new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/glob/.npmignore b/node_modules/grunt/node_modules/glob/.npmignore new file mode 100644 index 000000000..2af4b71c9 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/.npmignore @@ -0,0 +1,2 @@ +.*.swp +test/a/ diff --git a/node_modules/grunt/node_modules/glob/.travis.yml b/node_modules/grunt/node_modules/glob/.travis.yml new file mode 100644 index 000000000..baa0031d5 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/grunt/node_modules/glob/LICENSE b/node_modules/grunt/node_modules/glob/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt/node_modules/glob/README.md b/node_modules/grunt/node_modules/glob/README.md new file mode 100644 index 000000000..6e27df620 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/README.md @@ -0,0 +1,233 @@ +# Glob + +This is a glob implementation in JavaScript. It uses the `minimatch` +library to do its matching. + +## Attention: node-glob users! + +The API has changed dramatically between 2.x and 3.x. This library is +now 100% JavaScript, and the integer flags have been replaced with an +options object. + +Also, there's an event emitter class, proper tests, and all the other +things you've come to expect from node modules. + +And best of all, no compilation! + +## Usage + +```javascript +var glob = require("glob") + +// options is optional +glob("**/*.js", options, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. +}) +``` + +## Features + +Please see the [minimatch +documentation](https://github.com/isaacs/minimatch) for more details. + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` +* [minimatch documentation](https://github.com/isaacs/minimatch) + +## glob(pattern, [options], cb) + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* `cb` {Function} + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Perform an asynchronous glob search. + +## glob.sync(pattern, [options] + +* `pattern` {String} Pattern to be matched +* `options` {Object} +* return: {Array} filenames found matching the pattern + +Perform a synchronous glob search. + +## Class: glob.Glob + +Create a Glob object by instanting the `glob.Glob` class. + +```javascript +var Glob = require("glob").Glob +var mg = new Glob(pattern, options, cb) +``` + +It's an EventEmitter, and starts walking the filesystem to find matches +immediately. + +### new glob.Glob(pattern, [options], [cb]) + +* `pattern` {String} pattern to search for +* `options` {Object} +* `cb` {Function} Called when an error occurs, or matches are found + * `err` {Error | null} + * `matches` {Array} filenames found matching the pattern + +Note that if the `sync` flag is set in the options, then matches will +be immediately available on the `g.found` member. + +### Properties + +* `minimatch` The minimatch object that the glob uses. +* `options` The options object passed in. +* `error` The error encountered. When an error is encountered, the + glob object is in an undefined state, and should be discarded. +* `aborted` Boolean which is set to true when calling `abort()`. There + is no way at this time to continue a glob search after aborting, but + you can re-use the statCache to avoid having to duplicate syscalls. + +### Events + +* `end` When the matching is finished, this is emitted with all the + matches found. If the `nonull` option is set, and no match was found, + then the `matches` list contains the original pattern. The matches + are sorted, unless the `nosort` flag is set. +* `match` Every time a match is found, this is emitted with the matched. +* `error` Emitted when an unexpected error is encountered, or whenever + any fs error occurs if `options.strict` is set. +* `abort` When `abort()` is called, this event is raised. + +### Methods + +* `abort` Stop the search. + +### Options + +All the options that can be passed to Minimatch can also be passed to +Glob to change pattern matching behavior. Also, some have been added, +or have glob-specific ramifications. + +All options are false by default, unless otherwise noted. + +All options are added to the glob object, as well. + +* `cwd` The current working directory in which to search. Defaults + to `process.cwd()`. +* `root` The place where patterns starting with `/` will be mounted + onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix + systems, and `C:\` or some such on Windows.) +* `nomount` By default, a pattern starting with a forward-slash will be + "mounted" onto the root setting, so that a valid filesystem path is + returned. Set this flag to disable that behavior. +* `mark` Add a `/` character to directory matches. Note that this + requires additional stat calls. +* `nosort` Don't sort the results. +* `stat` Set to true to stat *all* results. This reduces performance + somewhat, and is completely unnecessary, unless `readdir` is presumed + to be an untrustworthy indicator of file existence. It will cause + ELOOP to be triggered one level sooner in the case of cyclical + symbolic links. +* `silent` When an unusual error is encountered + when attempting to read a directory, a warning will be printed to + stderr. Set the `silent` option to true to suppress these warnings. +* `strict` When an unusual error is encountered + when attempting to read a directory, the process will just continue on + in search of other matches. Set the `strict` option to raise an error + in these cases. +* `statCache` A cache of results of filesystem information, to prevent + unnecessary stat calls. While it should not normally be necessary to + set this, you may pass the statCache from one glob() call to the + options object of another, if you know that the filesystem will not + change between calls. (See "Race Conditions" below.) +* `sync` Perform a synchronous glob search. +* `nounique` In some cases, brace-expanded patterns can result in the + same file showing up multiple times in the result set. By default, + this implementation prevents duplicates in the result set. + Set this flag to disable that behavior. +* `nonull` Set to never return an empty set, instead returning a set + containing the pattern itself. This is the default in glob(3). +* `nocase` Perform a case-insensitive match. Note that case-insensitive + filesystems will sometimes result in glob returning results that are + case-insensitively matched anyway, since readdir and stat will not + raise an error. +* `debug` Set to enable debug logging in minimatch and glob. +* `globDebug` Set to enable debug logging in glob, but not minimatch. + +## Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between node-glob and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. **Note that this is different from the way that `**` is +handled by ruby's `Dir` class.** + +If an escaped pattern has no matches, and the `nonull` flag is set, +then glob returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + +## Windows + +**Please only use forward-slashes in glob expressions.** + +Though windows uses either `/` or `\` as its path separator, only `/` +characters are used by this glob implementation. You must use +forward-slashes **only** in glob expressions. Back-slashes will always +be interpreted as escape characters, not path separators. + +Results from absolute patterns such as `/foo/*` are mounted onto the +root setting using `path.join`. On windows, this will by default result +in `/foo/*` matching `C:\foo\bar.txt`. + +## Race Conditions + +Glob searching, by its very nature, is susceptible to race conditions, +since it relies on directory walking and such. + +As a result, it is possible that a file that exists when glob looks for +it may have been deleted or modified by the time it returns the result. + +As part of its internal implementation, this program caches all stat +and readdir calls that it makes, in order to cut down on system +overhead. However, this also makes it even more susceptible to races, +especially if the statCache object is reused between glob calls. + +Users are thus advised not to use a glob result as a +guarantee of filesystem state in the face of rapid changes. +For the vast majority of operations, this is never a problem. diff --git a/node_modules/grunt/node_modules/glob/examples/g.js b/node_modules/grunt/node_modules/glob/examples/g.js new file mode 100644 index 000000000..be122df00 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/examples/g.js @@ -0,0 +1,9 @@ +var Glob = require("../").Glob + +var pattern = "test/a/**/[cg]/../[cg]" +console.log(pattern) + +var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) { + console.log("matches", matches) +}) +console.log("after") diff --git a/node_modules/grunt/node_modules/glob/examples/usr-local.js b/node_modules/grunt/node_modules/glob/examples/usr-local.js new file mode 100644 index 000000000..327a425e4 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/examples/usr-local.js @@ -0,0 +1,9 @@ +var Glob = require("../").Glob + +var pattern = "{./*/*,/*,/usr/local/*}" +console.log(pattern) + +var mg = new Glob(pattern, {mark: true}, function (er, matches) { + console.log("matches", matches) +}) +console.log("after") diff --git a/node_modules/grunt/node_modules/glob/glob.js b/node_modules/grunt/node_modules/glob/glob.js new file mode 100644 index 000000000..891c88360 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/glob.js @@ -0,0 +1,643 @@ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// readdir(PREFIX) as ENTRIES +// If fails, END +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $]) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $]) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + + + +module.exports = glob + +var fs = require("graceful-fs") +, minimatch = require("minimatch") +, Minimatch = minimatch.Minimatch +, inherits = require("inherits") +, EE = require("events").EventEmitter +, path = require("path") +, isDir = {} +, assert = require("assert").ok + +function glob (pattern, options, cb) { + if (typeof options === "function") cb = options, options = {} + if (!options) options = {} + + if (typeof options === "number") { + deprecated() + return + } + + var g = new Glob(pattern, options, cb) + return g.sync ? g.found : g +} + +glob.fnmatch = deprecated + +function deprecated () { + throw new Error("glob's interface has changed. Please see the docs.") +} + +glob.sync = globSync +function globSync (pattern, options) { + if (typeof options === "number") { + deprecated() + return + } + + options = options || {} + options.sync = true + return glob(pattern, options) +} + + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (!(this instanceof Glob)) { + return new Glob(pattern, options, cb) + } + + if (typeof cb === "function") { + this.on("error", cb) + this.on("end", function (matches) { + cb(null, matches) + }) + } + + options = options || {} + + this.EOF = {} + this._emitQueue = [] + + this.maxDepth = options.maxDepth || 1000 + this.maxLength = options.maxLength || Infinity + this.statCache = options.statCache || {} + + this.changedCwd = false + var cwd = process.cwd() + if (!options.hasOwnProperty("cwd")) this.cwd = cwd + else { + this.cwd = options.cwd + this.changedCwd = path.resolve(options.cwd) !== cwd + } + + this.root = options.root || path.resolve(this.cwd, "/") + this.root = path.resolve(this.root) + if (process.platform === "win32") + this.root = this.root.replace(/\\/g, "/") + + this.nomount = !!options.nomount + + if (!pattern) { + throw new Error("must provide pattern") + } + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + this.strict = options.strict !== false + this.dot = !!options.dot + this.mark = !!options.mark + this.sync = !!options.sync + this.nounique = !!options.nounique + this.nonull = !!options.nonull + this.nosort = !!options.nosort + this.nocase = !!options.nocase + this.stat = !!options.stat + + this.debug = !!options.debug || !!options.globDebug + if (this.debug) + this.log = console.error + + this.silent = !!options.silent + + var mm = this.minimatch = new Minimatch(pattern, options) + this.options = mm.options + pattern = this.pattern = mm.pattern + + this.error = null + this.aborted = false + + EE.call(this) + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + this.minimatch.set.forEach(iterator.bind(this)) + function iterator (pattern, i, set) { + this._process(pattern, 0, i, function (er) { + if (er) this.emit("error", er) + if (-- n <= 0) this._finish() + }) + } +} + +Glob.prototype.log = function () {} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + + var nou = this.nounique + , all = nou ? [] : {} + + for (var i = 0, l = this.matches.length; i < l; i ++) { + var matches = this.matches[i] + this.log("matches[%d] =", i, matches) + // do like the shell, and spit out the literal glob + if (!matches) { + if (this.nonull) { + var literal = this.minimatch.globSet[i] + if (nou) all.push(literal) + else all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) all.push.apply(all, m) + else m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) all = Object.keys(all) + + if (!this.nosort) { + all = all.sort(this.nocase ? alphasorti : alphasort) + } + + if (this.mark) { + // at *some* point we statted all of these + all = all.map(function (m) { + var sc = this.statCache[m] + if (!sc) + return m + var isDir = (Array.isArray(sc) || sc === 2) + if (isDir && m.slice(-1) !== "/") { + return m + "/" + } + if (!isDir && m.slice(-1) === "/") { + return m.replace(/\/+$/, "") + } + return m + }, this) + } + + this.log("emitting end", all) + + this.EOF = this.found = all + this.emitMatch(this.EOF) +} + +function alphasorti (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return alphasort(a, b) +} + +function alphasort (a, b) { + return a > b ? 1 : a < b ? -1 : 0 +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit("abort") +} + +Glob.prototype.pause = function () { + if (this.paused) return + if (this.sync) + this.emit("error", new Error("Can't pause/resume sync glob")) + this.paused = true + this.emit("pause") +} + +Glob.prototype.resume = function () { + if (!this.paused) return + if (this.sync) + this.emit("error", new Error("Can't pause/resume sync glob")) + this.paused = false + this.emit("resume") + this._processEmitQueue() + //process.nextTick(this.emit.bind(this, "resume")) +} + +Glob.prototype.emitMatch = function (m) { + this._emitQueue.push(m) + this._processEmitQueue() +} + +Glob.prototype._processEmitQueue = function (m) { + while (!this._processingEmitQueue && + !this.paused) { + this._processingEmitQueue = true + var m = this._emitQueue.shift() + if (!m) { + this._processingEmitQueue = false + break + } + + this.log('emit!', m === this.EOF ? "end" : "match") + + this.emit(m === this.EOF ? "end" : "match", m) + this._processingEmitQueue = false + } +} + +Glob.prototype._process = function (pattern, depth, index, cb_) { + assert(this instanceof Glob) + + var cb = function cb (er, res) { + assert(this instanceof Glob) + if (this.paused) { + if (!this._processQueue) { + this._processQueue = [] + this.once("resume", function () { + var q = this._processQueue + this._processQueue = null + q.forEach(function (cb) { cb() }) + }) + } + this._processQueue.push(cb_.bind(this, er, res)) + } else { + cb_.call(this, er, res) + } + }.bind(this) + + if (this.aborted) return cb() + + if (depth > this.maxDepth) return cb() + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === "string") { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + prefix = pattern.join("/") + this._stat(prefix, function (exists, isDir) { + // either it's there, or it isn't. + // nothing more to do, either way. + if (exists) { + if (prefix && isAbsolute(prefix) && !this.nomount) { + if (prefix.charAt(0) === "/") { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + } + } + + if (process.platform === "win32") + prefix = prefix.replace(/\\/g, "/") + + this.matches[index] = this.matches[index] || {} + this.matches[index][prefix] = true + this.emitMatch(prefix) + } + return cb() + }) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's "absolute" like /foo/bar, + // or "relative" like "../baz" + prefix = pattern.slice(0, n) + prefix = prefix.join("/") + break + } + + // get the list of entries. + var read + if (prefix === null) read = "." + else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) { + if (!prefix || !isAbsolute(prefix)) { + prefix = path.join("/", prefix) + } + read = prefix = path.resolve(prefix) + + // if (process.platform === "win32") + // read = prefix = prefix.replace(/^[a-zA-Z]:|\\/g, "/") + + this.log('absolute: ', prefix, this.root, pattern, read) + } else { + read = prefix + } + + this.log('readdir(%j)', read, this.cwd, this.root) + + return this._readdir(read, function (er, entries) { + if (er) { + // not a directory! + // this means that, whatever else comes after this, it can never match + return cb() + } + + // globstar is special + if (pattern[n] === minimatch.GLOBSTAR) { + // test without the globstar, and with every child both below + // and replacing the globstar. + var s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ] + entries.forEach(function (e) { + if (e.charAt(0) === "." && !this.dot) return + // instead of the globstar + s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))) + // below the globstar + s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n))) + }, this) + + // now asyncForEach over this + var l = s.length + , errState = null + s.forEach(function (gsPattern) { + this._process(gsPattern, depth + 1, index, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (--l <= 0) return cb() + }) + }, this) + + return + } + + // not a globstar + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = pattern[n] + if (typeof pn === "string") { + var found = entries.indexOf(pn) !== -1 + entries = found ? entries[pn] : [] + } else { + var rawGlob = pattern[n]._glob + , dotOk = this.dot || rawGlob.charAt(0) === "." + + entries = entries.filter(function (e) { + return (e.charAt(0) !== "." || dotOk) && + (typeof pattern[n] === "string" && e === pattern[n] || + e.match(pattern[n])) + }) + } + + // If n === pattern.length - 1, then there's no need for the extra stat + // *unless* the user has specified "mark" or "stat" explicitly. + // We know that they exist, since the readdir returned them. + if (n === pattern.length - 1 && + !this.mark && + !this.stat) { + entries.forEach(function (e) { + if (prefix) { + if (prefix !== "/") e = prefix + "/" + e + else e = prefix + e + } + if (e.charAt(0) === "/" && !this.nomount) { + e = path.join(this.root, e) + } + + if (process.platform === "win32") + e = e.replace(/\\/g, "/") + + this.matches[index] = this.matches[index] || {} + this.matches[index][e] = true + this.emitMatch(e) + }, this) + return cb.call(this) + } + + + // now test all the remaining entries as stand-ins for that part + // of the pattern. + var l = entries.length + , errState = null + if (l === 0) return cb() // no matches possible + entries.forEach(function (e) { + var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)) + this._process(p, depth + 1, index, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (--l === 0) return cb.call(this) + }) + }, this) + }) + +} + +Glob.prototype._stat = function (f, cb) { + assert(this instanceof Glob) + var abs = f + if (f.charAt(0) === "/") { + abs = path.join(this.root, f) + } else if (this.changedCwd) { + abs = path.resolve(this.cwd, f) + } + this.log('stat', [this.cwd, f, '=', abs]) + if (f.length > this.maxLength) { + var er = new Error("Path name too long") + er.code = "ENAMETOOLONG" + er.path = f + return this._afterStat(f, abs, cb, er) + } + + if (this.statCache.hasOwnProperty(f)) { + var exists = this.statCache[f] + , isDir = exists && (Array.isArray(exists) || exists === 2) + if (this.sync) return cb.call(this, !!exists, isDir) + return process.nextTick(cb.bind(this, !!exists, isDir)) + } + + if (this.sync) { + var er, stat + try { + stat = fs.statSync(abs) + } catch (e) { + er = e + } + this._afterStat(f, abs, cb, er, stat) + } else { + fs.stat(abs, this._afterStat.bind(this, f, abs, cb)) + } +} + +Glob.prototype._afterStat = function (f, abs, cb, er, stat) { + var exists + assert(this instanceof Glob) + + if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) { + this.log("should be ENOTDIR, fake it") + + er = new Error("ENOTDIR, not a directory '" + abs + "'") + er.path = abs + er.code = "ENOTDIR" + stat = null + } + + if (er || !stat) { + exists = false + } else { + exists = stat.isDirectory() ? 2 : 1 + } + this.statCache[f] = this.statCache[f] || exists + cb.call(this, !!exists, exists === 2) +} + +Glob.prototype._readdir = function (f, cb) { + assert(this instanceof Glob) + var abs = f + if (f.charAt(0) === "/") { + abs = path.join(this.root, f) + } else if (isAbsolute(f)) { + abs = f + } else if (this.changedCwd) { + abs = path.resolve(this.cwd, f) + } + + this.log('readdir', [this.cwd, f, abs]) + if (f.length > this.maxLength) { + var er = new Error("Path name too long") + er.code = "ENAMETOOLONG" + er.path = f + return this._afterReaddir(f, abs, cb, er) + } + + if (this.statCache.hasOwnProperty(f)) { + var c = this.statCache[f] + if (Array.isArray(c)) { + if (this.sync) return cb.call(this, null, c) + return process.nextTick(cb.bind(this, null, c)) + } + + if (!c || c === 1) { + // either ENOENT or ENOTDIR + var code = c ? "ENOTDIR" : "ENOENT" + , er = new Error((c ? "Not a directory" : "Not found") + ": " + f) + er.path = f + er.code = code + this.log(f, er) + if (this.sync) return cb.call(this, er) + return process.nextTick(cb.bind(this, er)) + } + + // at this point, c === 2, meaning it's a dir, but we haven't + // had to read it yet, or c === true, meaning it's *something* + // but we don't have any idea what. Need to read it, either way. + } + + if (this.sync) { + var er, entries + try { + entries = fs.readdirSync(abs) + } catch (e) { + er = e + } + return this._afterReaddir(f, abs, cb, er, entries) + } + + fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb)) +} + +Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) { + assert(this instanceof Glob) + if (entries && !er) { + this.statCache[f] = entries + // if we haven't asked to stat everything for suresies, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. This also gets us one step + // further into ELOOP territory. + if (!this.mark && !this.stat) { + entries.forEach(function (e) { + if (f === "/") e = f + e + else e = f + "/" + e + this.statCache[e] = true + }, this) + } + + return cb.call(this, er, entries) + } + + // now handle errors, and cache the information + if (er) switch (er.code) { + case "ENOTDIR": // totally normal. means it *does* exist. + this.statCache[f] = 1 + return cb.call(this, er) + case "ENOENT": // not terribly unusual + case "ELOOP": + case "ENAMETOOLONG": + case "UNKNOWN": + this.statCache[f] = false + return cb.call(this, er) + default: // some unusual error. Treat as failure. + this.statCache[f] = false + if (this.strict) this.emit("error", er) + if (!this.silent) console.error("glob error", er) + return cb.call(this, er) + } +} + +var isAbsolute = process.platform === "win32" ? absWin : absUnix + +function absWin (p) { + if (absUnix(p)) return true + // pull off the device/UNC bit from a windows path. + // from node's lib/path.js + var splitDeviceRe = + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/ + , result = splitDeviceRe.exec(p) + , device = result[1] || '' + , isUnc = device && device.charAt(1) !== ':' + , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute + + return isAbsolute +} + +function absUnix (p) { + return p.charAt(0) === "/" || p === "" +} diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/.npmignore b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/.npmignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/LICENSE b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/README.md b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/README.md new file mode 100644 index 000000000..01af3d6b6 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/README.md @@ -0,0 +1,33 @@ +# graceful-fs + +graceful-fs functions as a drop-in replacement for the fs module, +making various improvements. + +The improvements are meant to normalize behavior across different +platforms and environments, and to make filesystem access more +resilient to errors. + +## Improvements over fs module + +graceful-fs: + +* keeps track of how many file descriptors are open, and by default + limits this to 1024. Any further requests to open a file are put in a + queue until new slots become available. If 1024 turns out to be too + much, it decreases the limit further. +* fixes `lchmod` for Node versions prior to 0.6.2. +* implements `fs.lutimes` if possible. Otherwise it becomes a noop. +* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or + `lchown` if the user isn't root. +* makes `lchmod` and `lchown` become noops, if not available. +* retries reading a file if `read` results in EAGAIN error. + +On Windows, it retries renaming a file for up to one second if `EACCESS` +or `EPERM` error occurs, likely because antivirus software has locked +the directory. + +## Configuration + +The maximum number of open file descriptors that graceful-fs manages may +be adjusted by setting `fs.MAX_OPEN` to a different number. The default +is 1024. diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/graceful-fs.js b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 000000000..ca9115243 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/graceful-fs.js @@ -0,0 +1,442 @@ +// this keeps a queue of opened file descriptors, and will make +// fs operations wait until some have closed before trying to open more. + +var fs = exports = module.exports = {} +fs._originalFs = require("fs") + +Object.getOwnPropertyNames(fs._originalFs).forEach(function(prop) { + var desc = Object.getOwnPropertyDescriptor(fs._originalFs, prop) + Object.defineProperty(fs, prop, desc) +}) + +var queue = [] + , constants = require("constants") + +fs._curOpen = 0 + +fs.MIN_MAX_OPEN = 64 +fs.MAX_OPEN = 1024 + +// prevent EMFILE errors +function OpenReq (path, flags, mode, cb) { + this.path = path + this.flags = flags + this.mode = mode + this.cb = cb +} + +function noop () {} + +fs.open = gracefulOpen + +function gracefulOpen (path, flags, mode, cb) { + if (typeof mode === "function") cb = mode, mode = null + if (typeof cb !== "function") cb = noop + + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new OpenReq(path, flags, mode, cb)) + setTimeout(flush) + return + } + open(path, flags, mode, function (er, fd) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + // that was too many. reduce max, get back in queue. + // this should only happen once in a great while, and only + // if the ulimit -n is set lower than 1024. + fs.MAX_OPEN = fs._curOpen - 1 + return fs.open(path, flags, mode, cb) + } + cb(er, fd) + }) +} + +function open (path, flags, mode, cb) { + cb = cb || noop + fs._curOpen ++ + fs._originalFs.open.call(fs, path, flags, mode, function (er, fd) { + if (er) onclose() + cb(er, fd) + }) +} + +fs.openSync = function (path, flags, mode) { + var ret + ret = fs._originalFs.openSync.call(fs, path, flags, mode) + fs._curOpen ++ + return ret +} + +function onclose () { + fs._curOpen -- + flush() +} + +function flush () { + while (fs._curOpen < fs.MAX_OPEN) { + var req = queue.shift() + if (!req) return + switch (req.constructor.name) { + case 'OpenReq': + open(req.path, req.flags || "r", req.mode || 0777, req.cb) + break + case 'ReaddirReq': + readdir(req.path, req.cb) + break + case 'ReadFileReq': + readFile(req.path, req.options, req.cb) + break + case 'WriteFileReq': + writeFile(req.path, req.data, req.options, req.cb) + break + default: + throw new Error('Unknown req type: ' + req.constructor.name) + } + } +} + +fs.close = function (fd, cb) { + cb = cb || noop + fs._originalFs.close.call(fs, fd, function (er) { + onclose() + cb(er) + }) +} + +fs.closeSync = function (fd) { + try { + return fs._originalFs.closeSync.call(fs, fd) + } finally { + onclose() + } +} + + +// readdir takes a fd as well. +// however, the sync version closes it right away, so +// there's no need to wrap. +// It would be nice to catch when it throws an EMFILE, +// but that's relatively rare anyway. + +fs.readdir = gracefulReaddir + +function gracefulReaddir (path, cb) { + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new ReaddirReq(path, cb)) + setTimeout(flush) + return + } + + readdir(path, function (er, files) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + fs.MAX_OPEN = fs._curOpen - 1 + return fs.readdir(path, cb) + } + cb(er, files) + }) +} + +function readdir (path, cb) { + cb = cb || noop + fs._curOpen ++ + fs._originalFs.readdir.call(fs, path, function (er, files) { + onclose() + cb(er, files) + }) +} + +function ReaddirReq (path, cb) { + this.path = path + this.cb = cb +} + + +fs.readFile = gracefulReadFile + +function gracefulReadFile(path, options, cb) { + if (typeof options === "function") cb = options, options = null + if (typeof cb !== "function") cb = noop + + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new ReadFileReq(path, options, cb)) + setTimeout(flush) + return + } + + readFile(path, options, function (er, data) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + fs.MAX_OPEN = fs._curOpen - 1 + return fs.readFile(path, options, cb) + } + cb(er, data) + }) +} + +function readFile (path, options, cb) { + cb = cb || noop + fs._curOpen ++ + fs._originalFs.readFile.call(fs, path, options, function (er, data) { + onclose() + cb(er, data) + }) +} + +function ReadFileReq (path, options, cb) { + this.path = path + this.options = options + this.cb = cb +} + + + + +fs.writeFile = gracefulWriteFile + +function gracefulWriteFile(path, data, options, cb) { + if (typeof options === "function") cb = options, options = null + if (typeof cb !== "function") cb = noop + + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new WriteFileReq(path, data, options, cb)) + setTimeout(flush) + return + } + + writeFile(path, data, options, function (er) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + fs.MAX_OPEN = fs._curOpen - 1 + return fs.writeFile(path, data, options, cb) + } + cb(er) + }) +} + +function writeFile (path, data, options, cb) { + cb = cb || noop + fs._curOpen ++ + fs._originalFs.writeFile.call(fs, path, data, options, function (er) { + onclose() + cb(er) + }) +} + +function WriteFileReq (path, data, options, cb) { + this.path = path + this.data = data + this.options = options + this.cb = cb +} + + +// (re-)implement some things that are known busted or missing. + +var constants = require("constants") + +// lchmod, broken prior to 0.6.2 +// back-port the fix here. +if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + fs.lchmod = function (path, mode, callback) { + callback = callback || noop + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var err, err2 + try { + var ret = fs.fchmodSync(fd, mode) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } +} + + +// lutimes implementation, or no-op +if (!fs.lutimes) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + cb = cb || noop + if (er) return cb(er) + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + return cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + , err + , err2 + , ret + + try { + var ret = fs.futimesSync(fd, at, mt) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } + + } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) { + // maybe utimensat will be bound soonish? + fs.lutimes = function (path, at, mt, cb) { + fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb) + } + + fs.lutimesSync = function (path, at, mt) { + return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW) + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) } + fs.lutimesSync = function () {} + } +} + + +// https://github.com/isaacs/node-graceful-fs/issues/4 +// Chown should not fail on einval or eperm if non-root. + +fs.chown = chownFix(fs.chown) +fs.fchown = chownFix(fs.fchown) +fs.lchown = chownFix(fs.lchown) + +fs.chownSync = chownFixSync(fs.chownSync) +fs.fchownSync = chownFixSync(fs.fchownSync) +fs.lchownSync = chownFixSync(fs.lchownSync) + +function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er, res) { + if (chownErOk(er)) er = null + cb(er, res) + }) + } +} + +function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + +function chownErOk (er) { + // if there's no getuid, or if getuid() is something other than 0, + // and the error is EINVAL or EPERM, then just ignore it. + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // When running as root, or if other types of errors are encountered, + // then it's strict. + if (!er || (!process.getuid || process.getuid() !== 0) + && (er.code === "EINVAL" || er.code === "EPERM")) return true +} + + +// if lchmod/lchown do not exist, then make them no-ops +if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + process.nextTick(cb) + } + fs.lchmodSync = function () {} +} +if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + process.nextTick(cb) + } + fs.lchownSync = function () {} +} + + + +// on Windows, A/V software can lock the directory, causing this +// to fail with an EACCES or EPERM if the directory contains newly +// created files. Try again on failure, for up to 1 second. +if (process.platform === "win32") { + var rename_ = fs.rename + fs.rename = function rename (from, to, cb) { + var start = Date.now() + rename_(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 1000) { + return rename_(from, to, CB) + } + cb(er) + }) + } +} + + +// if read() returns EAGAIN, then just try it again. +var read = fs.read +fs.read = function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return read.call(fs, fd, buffer, offset, length, position, callback) +} + +var readSync = fs.readSync +fs.readSync = function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } +} diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/package.json b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/package.json new file mode 100644 index 000000000..e044da3fd --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/package.json @@ -0,0 +1,48 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "graceful-fs", + "description": "A drop-in replacement for fs, making various improvements.", + "version": "1.2.3", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-graceful-fs.git" + }, + "main": "graceful-fs.js", + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "keywords": [ + "fs", + "module", + "reading", + "retry", + "retries", + "queue", + "error", + "errors", + "handling", + "EMFILE", + "EAGAIN", + "EINVAL", + "EPERM", + "EACCESS" + ], + "license": "BSD", + "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* keeps track of how many file descriptors are open, and by default\n limits this to 1024. Any further requests to open a file are put in a\n queue until new slots become available. If 1024 turns out to be too\n much, it decreases the limit further.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n\n## Configuration\n\nThe maximum number of open file descriptors that graceful-fs manages may\nbe adjusted by setting `fs.MAX_OPEN` to a different number. The default\nis 1024.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-graceful-fs/issues" + }, + "_id": "graceful-fs@1.2.3", + "_from": "graceful-fs@~1.2.0" +} diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/open.js b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/open.js new file mode 100644 index 000000000..930d53257 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/open.js @@ -0,0 +1,46 @@ +var test = require('tap').test +var fs = require('../graceful-fs.js') + +test('graceful fs is not fs', function (t) { + t.notEqual(fs, require('fs')) + t.end() +}) + +test('open an existing file works', function (t) { + var start = fs._curOpen + var fd = fs.openSync(__filename, 'r') + t.equal(fs._curOpen, start + 1) + fs.closeSync(fd) + t.equal(fs._curOpen, start) + fs.open(__filename, 'r', function (er, fd) { + if (er) throw er + t.equal(fs._curOpen, start + 1) + fs.close(fd, function (er) { + if (er) throw er + t.equal(fs._curOpen, start) + t.end() + }) + }) +}) + +test('open a non-existing file throws', function (t) { + var start = fs._curOpen + var er + try { + var fd = fs.openSync('this file does not exist', 'r') + } catch (x) { + er = x + } + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + t.equal(fs._curOpen, start) + + fs.open('neither does this file', 'r', function (er, fd) { + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + t.equal(fs._curOpen, start) + t.end() + }) +}) diff --git a/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/ulimit.js b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/ulimit.js new file mode 100644 index 000000000..8d0882d0c --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/graceful-fs/test/ulimit.js @@ -0,0 +1,158 @@ +var test = require('tap').test + +// simulated ulimit +// this is like graceful-fs, but in reverse +var fs_ = require('fs') +var fs = require('../graceful-fs.js') +var files = fs.readdirSync(__dirname) + +// Ok, no more actual file reading! + +var fds = 0 +var nextFd = 60 +var limit = 8 +fs_.open = function (path, flags, mode, cb) { + process.nextTick(function() { + ++fds + if (fds >= limit) { + --fds + var er = new Error('EMFILE Curses!') + er.code = 'EMFILE' + er.path = path + return cb(er) + } else { + cb(null, nextFd++) + } + }) +} + +fs_.openSync = function (path, flags, mode) { + if (fds >= limit) { + var er = new Error('EMFILE Curses!') + er.code = 'EMFILE' + er.path = path + throw er + } else { + ++fds + return nextFd++ + } +} + +fs_.close = function (fd, cb) { + process.nextTick(function () { + --fds + cb() + }) +} + +fs_.closeSync = function (fd) { + --fds +} + +fs_.readdir = function (path, cb) { + process.nextTick(function() { + if (fds >= limit) { + var er = new Error('EMFILE Curses!') + er.code = 'EMFILE' + er.path = path + return cb(er) + } else { + ++fds + process.nextTick(function () { + --fds + cb(null, [__filename, "some-other-file.js"]) + }) + } + }) +} + +fs_.readdirSync = function (path) { + if (fds >= limit) { + var er = new Error('EMFILE Curses!') + er.code = 'EMFILE' + er.path = path + throw er + } else { + return [__filename, "some-other-file.js"] + } +} + + +test('open emfile autoreduce', function (t) { + fs.MIN_MAX_OPEN = 4 + t.equal(fs.MAX_OPEN, 1024) + + var max = 12 + for (var i = 0; i < max; i++) { + fs.open(__filename, 'r', next(i)) + } + + var phase = 0 + + var expect = + [ [ 0, 60, null, 1024, 4, 12, 1 ], + [ 1, 61, null, 1024, 4, 12, 2 ], + [ 2, 62, null, 1024, 4, 12, 3 ], + [ 3, 63, null, 1024, 4, 12, 4 ], + [ 4, 64, null, 1024, 4, 12, 5 ], + [ 5, 65, null, 1024, 4, 12, 6 ], + [ 6, 66, null, 1024, 4, 12, 7 ], + [ 7, 67, null, 6, 4, 5, 1 ], + [ 8, 68, null, 6, 4, 5, 2 ], + [ 9, 69, null, 6, 4, 5, 3 ], + [ 10, 70, null, 6, 4, 5, 4 ], + [ 11, 71, null, 6, 4, 5, 5 ] ] + + var actual = [] + + function next (i) { return function (er, fd) { + if (er) + throw er + actual.push([i, fd, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds]) + + if (i === max - 1) { + t.same(actual, expect) + t.ok(fs.MAX_OPEN < limit) + t.end() + } + + fs.close(fd) + } } +}) + +test('readdir emfile autoreduce', function (t) { + fs.MAX_OPEN = 1024 + var max = 12 + for (var i = 0; i < max; i ++) { + fs.readdir(__dirname, next(i)) + } + + var expect = + [ [0,[__filename,"some-other-file.js"],null,7,4,7,7], + [1,[__filename,"some-other-file.js"],null,7,4,7,6], + [2,[__filename,"some-other-file.js"],null,7,4,7,5], + [3,[__filename,"some-other-file.js"],null,7,4,7,4], + [4,[__filename,"some-other-file.js"],null,7,4,7,3], + [5,[__filename,"some-other-file.js"],null,7,4,6,2], + [6,[__filename,"some-other-file.js"],null,7,4,5,1], + [7,[__filename,"some-other-file.js"],null,7,4,4,0], + [8,[__filename,"some-other-file.js"],null,7,4,3,3], + [9,[__filename,"some-other-file.js"],null,7,4,2,2], + [10,[__filename,"some-other-file.js"],null,7,4,1,1], + [11,[__filename,"some-other-file.js"],null,7,4,0,0] ] + + var actual = [] + + function next (i) { return function (er, files) { + if (er) + throw er + var line = [i, files, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds ] + actual.push(line) + + if (i === max - 1) { + t.ok(fs.MAX_OPEN < limit) + t.same(actual, expect) + t.end() + } + } } +}) diff --git a/node_modules/grunt/node_modules/glob/node_modules/inherits/README.md b/node_modules/grunt/node_modules/glob/node_modules/inherits/README.md new file mode 100644 index 000000000..b2beaed93 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/inherits/README.md @@ -0,0 +1,51 @@ +A dead simple way to do inheritance in JS. + + var inherits = require("inherits") + + function Animal () { + this.alive = true + } + Animal.prototype.say = function (what) { + console.log(what) + } + + inherits(Dog, Animal) + function Dog () { + Dog.super.apply(this) + } + Dog.prototype.sniff = function () { + this.say("sniff sniff") + } + Dog.prototype.bark = function () { + this.say("woof woof") + } + + inherits(Chihuahua, Dog) + function Chihuahua () { + Chihuahua.super.apply(this) + } + Chihuahua.prototype.bark = function () { + this.say("yip yip") + } + + // also works + function Cat () { + Cat.super.apply(this) + } + Cat.prototype.hiss = function () { + this.say("CHSKKSS!!") + } + inherits(Cat, Animal, { + meow: function () { this.say("miao miao") } + }) + Cat.prototype.purr = function () { + this.say("purr purr") + } + + + var c = new Chihuahua + assert(c instanceof Chihuahua) + assert(c instanceof Dog) + assert(c instanceof Animal) + +The actual function is laughably small. 10-lines small. diff --git a/node_modules/grunt/node_modules/glob/node_modules/inherits/inherits.js b/node_modules/grunt/node_modules/glob/node_modules/inherits/inherits.js new file mode 100644 index 000000000..061b39620 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/inherits/inherits.js @@ -0,0 +1,29 @@ +module.exports = inherits + +function inherits (c, p, proto) { + proto = proto || {} + var e = {} + ;[c.prototype, proto].forEach(function (s) { + Object.getOwnPropertyNames(s).forEach(function (k) { + e[k] = Object.getOwnPropertyDescriptor(s, k) + }) + }) + c.prototype = Object.create(p.prototype, e) + c.super = p +} + +//function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +//} +//function Parent () {} +//inherits(Child, Parent) +//new Child diff --git a/node_modules/grunt/node_modules/glob/node_modules/inherits/package.json b/node_modules/grunt/node_modules/glob/node_modules/inherits/package.json new file mode 100644 index 000000000..aae88dbbf --- /dev/null +++ b/node_modules/grunt/node_modules/glob/node_modules/inherits/package.json @@ -0,0 +1,30 @@ +{ + "name": "inherits", + "description": "A tiny simple way to do classic inheritance in js", + "version": "1.0.0", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented" + ], + "main": "./inherits.js", + "repository": { + "type": "git", + "url": "https://github.com/isaacs/inherits" + }, + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "readme": "A dead simple way to do inheritance in JS.\n\n var inherits = require(\"inherits\")\n\n function Animal () {\n this.alive = true\n }\n Animal.prototype.say = function (what) {\n console.log(what)\n }\n\n inherits(Dog, Animal)\n function Dog () {\n Dog.super.apply(this)\n }\n Dog.prototype.sniff = function () {\n this.say(\"sniff sniff\")\n }\n Dog.prototype.bark = function () {\n this.say(\"woof woof\")\n }\n\n inherits(Chihuahua, Dog)\n function Chihuahua () {\n Chihuahua.super.apply(this)\n }\n Chihuahua.prototype.bark = function () {\n this.say(\"yip yip\")\n }\n\n // also works\n function Cat () {\n Cat.super.apply(this)\n }\n Cat.prototype.hiss = function () {\n this.say(\"CHSKKSS!!\")\n }\n inherits(Cat, Animal, {\n meow: function () { this.say(\"miao miao\") }\n })\n Cat.prototype.purr = function () {\n this.say(\"purr purr\")\n }\n\n\n var c = new Chihuahua\n assert(c instanceof Chihuahua)\n assert(c instanceof Dog)\n assert(c instanceof Animal)\n\nThe actual function is laughably small. 10-lines small.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/inherits/issues" + }, + "_id": "inherits@1.0.0", + "_from": "inherits@1", + "scripts": {} +} diff --git a/node_modules/grunt/node_modules/glob/package.json b/node_modules/grunt/node_modules/glob/package.json new file mode 100644 index 000000000..e85a4ff62 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "name": "glob", + "description": "a little globber", + "version": "3.1.21", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-glob.git" + }, + "main": "glob.js", + "engines": { + "node": "*" + }, + "dependencies": { + "minimatch": "~0.2.11", + "graceful-fs": "~1.2.0", + "inherits": "1" + }, + "devDependencies": { + "tap": "~0.4.0", + "mkdirp": "0", + "rimraf": "1" + }, + "scripts": { + "test": "tap test/*.js" + }, + "license": "BSD", + "readme": "# Glob\n\nThis is a glob implementation in JavaScript. It uses the `minimatch`\nlibrary to do its matching.\n\n## Attention: node-glob users!\n\nThe API has changed dramatically between 2.x and 3.x. This library is\nnow 100% JavaScript, and the integer flags have been replaced with an\noptions object.\n\nAlso, there's an event emitter class, proper tests, and all the other\nthings you've come to expect from node modules.\n\nAnd best of all, no compilation!\n\n## Usage\n\n```javascript\nvar glob = require(\"glob\")\n\n// options is optional\nglob(\"**/*.js\", options, function (er, files) {\n // files is an array of filenames.\n // If the `nonull` option is set, and nothing\n // was found, then files is [\"**/*.js\"]\n // er is an error object or null.\n})\n```\n\n## Features\n\nPlease see the [minimatch\ndocumentation](https://github.com/isaacs/minimatch) for more details.\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n* [minimatch documentation](https://github.com/isaacs/minimatch)\n\n## glob(pattern, [options], cb)\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* `cb` {Function}\n * `err` {Error | null}\n * `matches` {Array} filenames found matching the pattern\n\nPerform an asynchronous glob search.\n\n## glob.sync(pattern, [options]\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* return: {Array} filenames found matching the pattern\n\nPerform a synchronous glob search.\n\n## Class: glob.Glob\n\nCreate a Glob object by instanting the `glob.Glob` class.\n\n```javascript\nvar Glob = require(\"glob\").Glob\nvar mg = new Glob(pattern, options, cb)\n```\n\nIt's an EventEmitter, and starts walking the filesystem to find matches\nimmediately.\n\n### new glob.Glob(pattern, [options], [cb])\n\n* `pattern` {String} pattern to search for\n* `options` {Object}\n* `cb` {Function} Called when an error occurs, or matches are found\n * `err` {Error | null}\n * `matches` {Array} filenames found matching the pattern\n\nNote that if the `sync` flag is set in the options, then matches will\nbe immediately available on the `g.found` member.\n\n### Properties\n\n* `minimatch` The minimatch object that the glob uses.\n* `options` The options object passed in.\n* `error` The error encountered. When an error is encountered, the\n glob object is in an undefined state, and should be discarded.\n* `aborted` Boolean which is set to true when calling `abort()`. There\n is no way at this time to continue a glob search after aborting, but\n you can re-use the statCache to avoid having to duplicate syscalls.\n\n### Events\n\n* `end` When the matching is finished, this is emitted with all the\n matches found. If the `nonull` option is set, and no match was found,\n then the `matches` list contains the original pattern. The matches\n are sorted, unless the `nosort` flag is set.\n* `match` Every time a match is found, this is emitted with the matched.\n* `error` Emitted when an unexpected error is encountered, or whenever\n any fs error occurs if `options.strict` is set.\n* `abort` When `abort()` is called, this event is raised.\n\n### Methods\n\n* `abort` Stop the search.\n\n### Options\n\nAll the options that can be passed to Minimatch can also be passed to\nGlob to change pattern matching behavior. Also, some have been added,\nor have glob-specific ramifications.\n\nAll options are false by default, unless otherwise noted.\n\nAll options are added to the glob object, as well.\n\n* `cwd` The current working directory in which to search. Defaults\n to `process.cwd()`.\n* `root` The place where patterns starting with `/` will be mounted\n onto. Defaults to `path.resolve(options.cwd, \"/\")` (`/` on Unix\n systems, and `C:\\` or some such on Windows.)\n* `nomount` By default, a pattern starting with a forward-slash will be\n \"mounted\" onto the root setting, so that a valid filesystem path is\n returned. Set this flag to disable that behavior.\n* `mark` Add a `/` character to directory matches. Note that this\n requires additional stat calls.\n* `nosort` Don't sort the results.\n* `stat` Set to true to stat *all* results. This reduces performance\n somewhat, and is completely unnecessary, unless `readdir` is presumed\n to be an untrustworthy indicator of file existence. It will cause\n ELOOP to be triggered one level sooner in the case of cyclical\n symbolic links.\n* `silent` When an unusual error is encountered\n when attempting to read a directory, a warning will be printed to\n stderr. Set the `silent` option to true to suppress these warnings.\n* `strict` When an unusual error is encountered\n when attempting to read a directory, the process will just continue on\n in search of other matches. Set the `strict` option to raise an error\n in these cases.\n* `statCache` A cache of results of filesystem information, to prevent\n unnecessary stat calls. While it should not normally be necessary to\n set this, you may pass the statCache from one glob() call to the\n options object of another, if you know that the filesystem will not\n change between calls. (See \"Race Conditions\" below.)\n* `sync` Perform a synchronous glob search.\n* `nounique` In some cases, brace-expanded patterns can result in the\n same file showing up multiple times in the result set. By default,\n this implementation prevents duplicates in the result set.\n Set this flag to disable that behavior.\n* `nonull` Set to never return an empty set, instead returning a set\n containing the pattern itself. This is the default in glob(3).\n* `nocase` Perform a case-insensitive match. Note that case-insensitive\n filesystems will sometimes result in glob returning results that are\n case-insensitively matched anyway, since readdir and stat will not\n raise an error.\n* `debug` Set to enable debug logging in minimatch and glob.\n* `globDebug` Set to enable debug logging in glob, but not minimatch.\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between node-glob and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen glob returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`glob.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n## Windows\n\n**Please only use forward-slashes in glob expressions.**\n\nThough windows uses either `/` or `\\` as its path separator, only `/`\ncharacters are used by this glob implementation. You must use\nforward-slashes **only** in glob expressions. Back-slashes will always\nbe interpreted as escape characters, not path separators.\n\nResults from absolute patterns such as `/foo/*` are mounted onto the\nroot setting using `path.join`. On windows, this will by default result\nin `/foo/*` matching `C:\\foo\\bar.txt`.\n\n## Race Conditions\n\nGlob searching, by its very nature, is susceptible to race conditions,\nsince it relies on directory walking and such.\n\nAs a result, it is possible that a file that exists when glob looks for\nit may have been deleted or modified by the time it returns the result.\n\nAs part of its internal implementation, this program caches all stat\nand readdir calls that it makes, in order to cut down on system\noverhead. However, this also makes it even more susceptible to races,\nespecially if the statCache object is reused between glob calls.\n\nUsers are thus advised not to use a glob result as a\nguarantee of filesystem state in the face of rapid changes.\nFor the vast majority of operations, this is never a problem.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-glob/issues" + }, + "_id": "glob@3.1.21", + "_from": "glob@~3.1.21" +} diff --git a/node_modules/grunt/node_modules/glob/test/00-setup.js b/node_modules/grunt/node_modules/glob/test/00-setup.js new file mode 100644 index 000000000..245afafda --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/00-setup.js @@ -0,0 +1,176 @@ +// just a little pre-run script to set up the fixtures. +// zz-finish cleans it up + +var mkdirp = require("mkdirp") +var path = require("path") +var i = 0 +var tap = require("tap") +var fs = require("fs") +var rimraf = require("rimraf") + +var files = +[ "a/.abcdef/x/y/z/a" +, "a/abcdef/g/h" +, "a/abcfed/g/h" +, "a/b/c/d" +, "a/bc/e/f" +, "a/c/d/c/b" +, "a/cb/e/f" +] + +var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c") +var symlinkFrom = "../.." + +files = files.map(function (f) { + return path.resolve(__dirname, f) +}) + +tap.test("remove fixtures", function (t) { + rimraf(path.resolve(__dirname, "a"), function (er) { + t.ifError(er, "remove fixtures") + t.end() + }) +}) + +files.forEach(function (f) { + tap.test(f, function (t) { + var d = path.dirname(f) + mkdirp(d, 0755, function (er) { + if (er) { + t.fail(er) + return t.bailout() + } + fs.writeFile(f, "i like tests", function (er) { + t.ifError(er, "make file") + t.end() + }) + }) + }) +}) + +if (process.platform !== "win32") { + tap.test("symlinky", function (t) { + var d = path.dirname(symlinkTo) + console.error("mkdirp", d) + mkdirp(d, 0755, function (er) { + t.ifError(er) + fs.symlink(symlinkFrom, symlinkTo, "dir", function (er) { + t.ifError(er, "make symlink") + t.end() + }) + }) + }) +} + +;["foo","bar","baz","asdf","quux","qwer","rewq"].forEach(function (w) { + w = "/tmp/glob-test/" + w + tap.test("create " + w, function (t) { + mkdirp(w, function (er) { + if (er) + throw er + t.pass(w) + t.end() + }) + }) +}) + + +// generate the bash pattern test-fixtures if possible +if (process.platform === "win32" || !process.env.TEST_REGEN) { + console.error("Windows, or TEST_REGEN unset. Using cached fixtures.") + return +} + +var spawn = require("child_process").spawn; +var globs = + // put more patterns here. + // anything that would be directly in / should be in /tmp/glob-test + ["test/a/*/+(c|g)/./d" + ,"test/a/**/[cg]/../[cg]" + ,"test/a/{b,c,d,e,f}/**/g" + ,"test/a/b/**" + ,"test/**/g" + ,"test/a/abc{fed,def}/g/h" + ,"test/a/abc{fed/g,def}/**/" + ,"test/a/abc{fed/g,def}/**///**/" + ,"test/**/a/**/" + ,"test/+(a|b|c)/a{/,bc*}/**" + ,"test/*/*/*/f" + ,"test/**/f" + ,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**" + ,"{./*/*,/tmp/glob-test/*}" + ,"{/tmp/glob-test/*,*}" // evil owl face! how you taunt me! + ,"test/a/!(symlink)/**" + ] +var bashOutput = {} +var fs = require("fs") + +globs.forEach(function (pattern) { + tap.test("generate fixture " + pattern, function (t) { + var cmd = "shopt -s globstar && " + + "shopt -s extglob && " + + "shopt -s nullglob && " + + // "shopt >&2; " + + "eval \'for i in " + pattern + "; do echo $i; done\'" + var cp = spawn("bash", ["-c", cmd], { cwd: path.dirname(__dirname) }) + var out = [] + cp.stdout.on("data", function (c) { + out.push(c) + }) + cp.stderr.pipe(process.stderr) + cp.on("close", function (code) { + out = flatten(out) + if (!out) + out = [] + else + out = cleanResults(out.split(/\r*\n/)) + + bashOutput[pattern] = out + t.notOk(code, "bash test should finish nicely") + t.end() + }) + }) +}) + +tap.test("save fixtures", function (t) { + var fname = path.resolve(__dirname, "bash-results.json") + var data = JSON.stringify(bashOutput, null, 2) + "\n" + fs.writeFile(fname, data, function (er) { + t.ifError(er) + t.end() + }) +}) + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/') + }) +} + +function flatten (chunks) { + var s = 0 + chunks.forEach(function (c) { s += c.length }) + var out = new Buffer(s) + s = 0 + chunks.forEach(function (c) { + c.copy(out, s) + s += c.length + }) + + return out.toString().trim() +} + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} diff --git a/node_modules/grunt/node_modules/glob/test/bash-comparison.js b/node_modules/grunt/node_modules/glob/test/bash-comparison.js new file mode 100644 index 000000000..239ed1a9c --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/bash-comparison.js @@ -0,0 +1,63 @@ +// basic test +// show that it does the same thing by default as the shell. +var tap = require("tap") +, child_process = require("child_process") +, bashResults = require("./bash-results.json") +, globs = Object.keys(bashResults) +, glob = require("../") +, path = require("path") + +// run from the root of the project +// this is usually where you're at anyway, but be sure. +process.chdir(path.resolve(__dirname, "..")) + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} + +globs.forEach(function (pattern) { + var expect = bashResults[pattern] + // anything regarding the symlink thing will fail on windows, so just skip it + if (process.platform === "win32" && + expect.some(function (m) { + return /\/symlink\//.test(m) + })) + return + + tap.test(pattern, function (t) { + glob(pattern, function (er, matches) { + if (er) + throw er + + // sort and unmark, just to match the shell results + matches = cleanResults(matches) + + t.deepEqual(matches, expect, pattern) + t.end() + }) + }) + + tap.test(pattern + " sync", function (t) { + var matches = cleanResults(glob.sync(pattern)) + + t.deepEqual(matches, expect, "should match shell") + t.end() + }) +}) + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:[\/\\]+/, '/').replace(/[\\\/]+/g, '/') + }) +} diff --git a/node_modules/grunt/node_modules/glob/test/bash-results.json b/node_modules/grunt/node_modules/glob/test/bash-results.json new file mode 100644 index 000000000..c227449b6 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/bash-results.json @@ -0,0 +1,348 @@ +{ + "test/a/*/+(c|g)/./d": [ + "test/a/b/c/./d" + ], + "test/a/**/[cg]/../[cg]": [ + "test/a/abcdef/g/../g", + "test/a/abcfed/g/../g", + "test/a/b/c/../c", + "test/a/c/../c", + "test/a/c/d/c/../c", + "test/a/symlink/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c" + ], + "test/a/{b,c,d,e,f}/**/g": [], + "test/a/b/**": [ + "test/a/b", + "test/a/b/c", + "test/a/b/c/d" + ], + "test/**/g": [ + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/a/abc{fed,def}/g/h": [ + "test/a/abcdef/g/h", + "test/a/abcfed/g/h" + ], + "test/a/abc{fed/g,def}/**/": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/a/abc{fed/g,def}/**///**/": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed/g" + ], + "test/**/a/**/": [ + "test/a", + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/b", + "test/a/b/c", + "test/a/bc", + "test/a/bc/e", + "test/a/c", + "test/a/c/d", + "test/a/c/d/c", + "test/a/cb", + "test/a/cb/e", + "test/a/symlink", + "test/a/symlink/a", + "test/a/symlink/a/b", + "test/a/symlink/a/b/c", + "test/a/symlink/a/b/c/a", + "test/a/symlink/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b" + ], + "test/+(a|b|c)/a{/,bc*}/**": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcdef/g/h", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/abcfed/g/h" + ], + "test/*/*/*/f": [ + "test/a/bc/e/f", + "test/a/cb/e/f" + ], + "test/**/f": [ + "test/a/bc/e/f", + "test/a/cb/e/f" + ], + "test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**": [ + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b", + "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c" + ], + "{./*/*,/tmp/glob-test/*}": [ + "./examples/g.js", + "./examples/usr-local.js", + "./node_modules/graceful-fs", + "./node_modules/inherits", + "./node_modules/minimatch", + "./node_modules/mkdirp", + "./node_modules/rimraf", + "./node_modules/tap", + "./test/00-setup.js", + "./test/a", + "./test/bash-comparison.js", + "./test/bash-results.json", + "./test/cwd-test.js", + "./test/mark.js", + "./test/nocase-nomagic.js", + "./test/pause-resume.js", + "./test/root-nomount.js", + "./test/root.js", + "./test/zz-cleanup.js", + "/tmp/glob-test/asdf", + "/tmp/glob-test/bar", + "/tmp/glob-test/baz", + "/tmp/glob-test/foo", + "/tmp/glob-test/quux", + "/tmp/glob-test/qwer", + "/tmp/glob-test/rewq" + ], + "{/tmp/glob-test/*,*}": [ + "/tmp/glob-test/asdf", + "/tmp/glob-test/bar", + "/tmp/glob-test/baz", + "/tmp/glob-test/foo", + "/tmp/glob-test/quux", + "/tmp/glob-test/qwer", + "/tmp/glob-test/rewq", + "examples", + "glob.js", + "LICENSE", + "node_modules", + "package.json", + "README.md", + "test" + ], + "test/a/!(symlink)/**": [ + "test/a/abcdef", + "test/a/abcdef/g", + "test/a/abcdef/g/h", + "test/a/abcfed", + "test/a/abcfed/g", + "test/a/abcfed/g/h", + "test/a/b", + "test/a/b/c", + "test/a/b/c/d", + "test/a/bc", + "test/a/bc/e", + "test/a/bc/e/f", + "test/a/c", + "test/a/c/d", + "test/a/c/d/c", + "test/a/c/d/c/b", + "test/a/cb", + "test/a/cb/e", + "test/a/cb/e/f" + ] +} diff --git a/node_modules/grunt/node_modules/glob/test/cwd-test.js b/node_modules/grunt/node_modules/glob/test/cwd-test.js new file mode 100644 index 000000000..352c27efa --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/cwd-test.js @@ -0,0 +1,55 @@ +var tap = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +tap.test("changing cwd and searching for **/d", function (t) { + var glob = require('../') + var path = require('path') + t.test('.', function (t) { + glob('**/d', function (er, matches) { + t.ifError(er) + t.like(matches, [ 'a/b/c/d', 'a/c/d' ]) + t.end() + }) + }) + + t.test('a', function (t) { + glob('**/d', {cwd:path.resolve('a')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'b/c/d', 'c/d' ]) + t.end() + }) + }) + + t.test('a/b', function (t) { + glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'c/d' ]) + t.end() + }) + }) + + t.test('a/b/', function (t) { + glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'c/d' ]) + t.end() + }) + }) + + t.test('.', function (t) { + glob('**/d', {cwd: process.cwd()}, function (er, matches) { + t.ifError(er) + t.like(matches, [ 'a/b/c/d', 'a/c/d' ]) + t.end() + }) + }) + + t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() + }) + + t.end() +}) diff --git a/node_modules/grunt/node_modules/glob/test/mark.js b/node_modules/grunt/node_modules/glob/test/mark.js new file mode 100644 index 000000000..ed68a335c --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/mark.js @@ -0,0 +1,74 @@ +var test = require("tap").test +var glob = require('../') +process.chdir(__dirname) + +test("mark, no / on pattern", function (t) { + glob("a/*", {mark: true}, function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + + if (process.platform !== "win32") + expect.push('a/symlink/') + + t.same(results, expect) + t.end() + }) +}) + +test("mark=false, no / on pattern", function (t) { + glob("a/*", function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef', + 'a/abcfed', + 'a/b', + 'a/bc', + 'a/c', + 'a/cb' ] + + if (process.platform !== "win32") + expect.push('a/symlink') + t.same(results, expect) + t.end() + }) +}) + +test("mark=true, / on pattern", function (t) { + glob("a/*/", {mark: true}, function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + if (process.platform !== "win32") + expect.push('a/symlink/') + t.same(results, expect) + t.end() + }) +}) + +test("mark=false, / on pattern", function (t) { + glob("a/*/", function (er, results) { + if (er) + throw er + var expect = [ 'a/abcdef/', + 'a/abcfed/', + 'a/b/', + 'a/bc/', + 'a/c/', + 'a/cb/' ] + if (process.platform !== "win32") + expect.push('a/symlink/') + t.same(results, expect) + t.end() + }) +}) diff --git a/node_modules/grunt/node_modules/glob/test/nocase-nomagic.js b/node_modules/grunt/node_modules/glob/test/nocase-nomagic.js new file mode 100644 index 000000000..d86297098 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/nocase-nomagic.js @@ -0,0 +1,113 @@ +var fs = require('graceful-fs'); +var test = require('tap').test; +var glob = require('../'); + +test('mock fs', function(t) { + var stat = fs.stat + var statSync = fs.statSync + var readdir = fs.readdir + var readdirSync = fs.readdirSync + + function fakeStat(path) { + var ret + switch (path.toLowerCase()) { + case '/tmp': case '/tmp/': + ret = { isDirectory: function() { return true } } + break + case '/tmp/a': + ret = { isDirectory: function() { return false } } + break + } + return ret + } + + fs.stat = function(path, cb) { + var f = fakeStat(path); + if (f) { + process.nextTick(function() { + cb(null, f) + }) + } else { + stat.call(fs, path, cb) + } + } + + fs.statSync = function(path) { + return fakeStat(path) || statSync.call(fs, path) + } + + function fakeReaddir(path) { + var ret + switch (path.toLowerCase()) { + case '/tmp': case '/tmp/': + ret = [ 'a', 'A' ] + break + case '/': + ret = ['tmp', 'tMp', 'tMP', 'TMP'] + } + return ret + } + + fs.readdir = function(path, cb) { + var f = fakeReaddir(path) + if (f) + process.nextTick(function() { + cb(null, f) + }) + else + readdir.call(fs, path, cb) + } + + fs.readdirSync = function(path) { + return fakeReaddir(path) || readdirSync.call(fs, path) + } + + t.pass('mocked') + t.end() +}) + +test('nocase, nomagic', function(t) { + var n = 2 + var want = [ '/TMP/A', + '/TMP/a', + '/tMP/A', + '/tMP/a', + '/tMp/A', + '/tMp/a', + '/tmp/A', + '/tmp/a' ] + glob('/tmp/a', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + if (--n === 0) t.end() + }) + glob('/tmp/A', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + if (--n === 0) t.end() + }) +}) + +test('nocase, with some magic', function(t) { + t.plan(2) + var want = [ '/TMP/A', + '/TMP/a', + '/tMP/A', + '/tMP/a', + '/tMp/A', + '/tMp/a', + '/tmp/A', + '/tmp/a' ] + glob('/tmp/*', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + }) + glob('/tmp/*', { nocase: true }, function(er, res) { + if (er) + throw er + t.same(res.sort(), want) + }) +}) diff --git a/node_modules/grunt/node_modules/glob/test/pause-resume.js b/node_modules/grunt/node_modules/glob/test/pause-resume.js new file mode 100644 index 000000000..e1ffbab1c --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/pause-resume.js @@ -0,0 +1,73 @@ +// show that no match events happen while paused. +var tap = require("tap") +, child_process = require("child_process") +// just some gnarly pattern with lots of matches +, pattern = "test/a/!(symlink)/**" +, bashResults = require("./bash-results.json") +, patterns = Object.keys(bashResults) +, glob = require("../") +, Glob = glob.Glob +, path = require("path") + +// run from the root of the project +// this is usually where you're at anyway, but be sure. +process.chdir(path.resolve(__dirname, "..")) + +function alphasort (a, b) { + a = a.toLowerCase() + b = b.toLowerCase() + return a > b ? 1 : a < b ? -1 : 0 +} + +function cleanResults (m) { + // normalize discrepancies in ordering, duplication, + // and ending slashes. + return m.map(function (m) { + return m.replace(/\/+/g, "/").replace(/\/$/, "") + }).sort(alphasort).reduce(function (set, f) { + if (f !== set[set.length - 1]) set.push(f) + return set + }, []).sort(alphasort).map(function (f) { + // de-windows + return (process.platform !== 'win32') ? f + : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/') + }) +} + +var globResults = [] +tap.test("use a Glob object, and pause/resume it", function (t) { + var g = new Glob(pattern) + , paused = false + , res = [] + , expect = bashResults[pattern] + + g.on("pause", function () { + console.error("pause") + }) + + g.on("resume", function () { + console.error("resume") + }) + + g.on("match", function (m) { + t.notOk(g.paused, "must not be paused") + globResults.push(m) + g.pause() + t.ok(g.paused, "must be paused") + setTimeout(g.resume.bind(g), 10) + }) + + g.on("end", function (matches) { + t.pass("reached glob end") + globResults = cleanResults(globResults) + matches = cleanResults(matches) + t.deepEqual(matches, globResults, + "end event matches should be the same as match events") + + t.deepEqual(matches, expect, + "glob matches should be the same as bash results") + + t.end() + }) +}) + diff --git a/node_modules/grunt/node_modules/glob/test/root-nomount.js b/node_modules/grunt/node_modules/glob/test/root-nomount.js new file mode 100644 index 000000000..3ac5979b0 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/root-nomount.js @@ -0,0 +1,39 @@ +var tap = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +tap.test("changing root and searching for /b*/**", function (t) { + var glob = require('../') + var path = require('path') + t.test('.', function (t) { + glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, []) + t.end() + }) + }) + + t.test('a', function (t) { + glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ]) + t.end() + }) + }) + + t.test('root=a, cwd=a/b', function (t) { + glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ]) + t.end() + }) + }) + + t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() + }) + + t.end() +}) diff --git a/node_modules/grunt/node_modules/glob/test/root.js b/node_modules/grunt/node_modules/glob/test/root.js new file mode 100644 index 000000000..95c23f99c --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/root.js @@ -0,0 +1,46 @@ +var t = require("tap") + +var origCwd = process.cwd() +process.chdir(__dirname) + +var glob = require('../') +var path = require('path') + +t.test('.', function (t) { + glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) { + t.ifError(er) + t.like(matches, []) + t.end() + }) +}) + + +t.test('a', function (t) { + console.error("root=" + path.resolve('a')) + glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) { + t.ifError(er) + var wanted = [ + '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' + ].map(function (m) { + return path.join(path.resolve('a'), m).replace(/\\/g, '/') + }) + + t.like(matches, wanted) + t.end() + }) +}) + +t.test('root=a, cwd=a/b', function (t) { + glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) { + t.ifError(er) + t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) { + return path.join(path.resolve('a'), m).replace(/\\/g, '/') + })) + t.end() + }) +}) + +t.test('cd -', function (t) { + process.chdir(origCwd) + t.end() +}) diff --git a/node_modules/grunt/node_modules/glob/test/zz-cleanup.js b/node_modules/grunt/node_modules/glob/test/zz-cleanup.js new file mode 100644 index 000000000..e085f0fa7 --- /dev/null +++ b/node_modules/grunt/node_modules/glob/test/zz-cleanup.js @@ -0,0 +1,11 @@ +// remove the fixtures +var tap = require("tap") +, rimraf = require("rimraf") +, path = require("path") + +tap.test("cleanup fixtures", function (t) { + rimraf(path.resolve(__dirname, "a"), function (er) { + t.ifError(er, "removed") + t.end() + }) +}) diff --git a/node_modules/grunt/node_modules/hooker/LICENSE-MIT b/node_modules/grunt/node_modules/hooker/LICENSE-MIT new file mode 100644 index 000000000..90c336c39 --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 "Cowboy" Ben Alman + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/hooker/README.md b/node_modules/grunt/node_modules/hooker/README.md new file mode 100644 index 000000000..138943a21 --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/README.md @@ -0,0 +1,186 @@ +# JavaScript Hooker + +Monkey-patch (hook) functions for debugging and stuff. + +## Getting Started + +This code should work just fine in Node.js: + +First, install the module with: `npm install hooker` + +```javascript +var hooker = require('hooker'); +hooker.hook(Math, "max", function() { + console.log(arguments.length + " arguments passed"); +}); +Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 +``` + +Or in the browser: + +```html + + +``` + +In the browser, you can attach Hooker's methods to any object. + +```html + + + +``` + +## Documentation + +### hooker.hook +Monkey-patch (hook) one or more methods of an object. +#### Signature: +`hooker.hook(object, [ props, ] [options | prehookFunction])` +#### `props` +The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all enumerable methods of `object` will be hooked. +#### `options` +* `pre` - (Function) a pre-hook function to be executed before the original function. Arguments passed into the method will be passed into the pre-hook function as well. +* `post` - (Function) a post-hook function to be executed after the original function. The original function's result is passed into the post-hook function as its first argument, followed by the method arguments. +* `once` - (Boolean) if true, auto-unhook the function after the first execution. +* `passName` - (Boolean) if true, pass the name of the method into the pre-hook function as its first arg (preceding all other arguments), and into the post-hook function as the second arg (after result but preceding all other arguments). + +#### Returns: +An array of hooked method names. + +### hooker.unhook +Un-monkey-patch (unhook) one or more methods of an object. +#### Signature: +`hooker.unhook(object [, props ])` +#### `props` +The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all methods of `object` will be unhooked. +#### Returns: +An array of unhooked method names. + +### hooker.orig +Get a reference to the original method from a hooked function. +#### Signature: +`hooker.orig(object, props)` + +### hooker.override +When a pre- or post-hook returns the result of this function, the value +passed will be used in place of the original function's return value. Any +post-hook override value will take precedence over a pre-hook override value. +#### Signature: +`hooker.override(value)` + +### hooker.preempt +When a pre-hook returns the result of this function, the value passed will +be used in place of the original function's return value, and the original +function will NOT be executed. +#### Signature: +`hooker.preempt(value)` + +### hooker.filter +When a pre-hook returns the result of this function, the context and +arguments passed will be applied into the original function. +#### Signature: +`hooker.filter(context, arguments)` + + +## Examples +See the unit tests for more examples. + +```javascript +var hooker = require('hooker'); +// Simple logging. +hooker.hook(Math, "max", function() { + console.log(arguments.length + " arguments passed"); +}); +Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 + +hooker.unhook(Math, "max"); // (This is assumed between all further examples) +Math.max(5, 6, 7) // 7 + +// Returning hooker.override(value) overrides the original value. +hooker.hook(Math, "max", function() { + if (arguments.length === 0) { + return hooker.override(9000); + } +}); +Math.max(5, 6, 7) // 7 +Math.max() // 9000 + +// Auto-unhook after one execution. +hooker.hook(Math, "max", { + once: true, + pre: function() { + console.log("Init something here"); + } +}); +Math.max(5, 6, 7) // logs: "Init something here", returns 7 +Math.max(5, 6, 7) // 7 + +// Filter `this` and arguments through a pre-hook function. +hooker.hook(Math, "max", { + pre: function() { + var args = [].map.call(arguments, function(num) { + return num * 2; + }); + return hooker.filter(this, args); // thisValue, arguments + } +}); +Math.max(5, 6, 7) // 14 + +// Modify the original function's result with a post-hook function. +hooker.hook(Math, "max", { + post: function(result) { + return hooker.override(result * 100); + } +}); +Math.max(5, 6, 7) // 700 + +// Hook every Math method. Note: if Math's methods were enumerable, the second +// argument could be omitted. Since they aren't, an array of properties to hook +// must be explicitly passed. Non-method properties will be skipped. +// See a more generic example here: http://bit.ly/vvJlrS +hooker.hook(Math, Object.getOwnPropertyNames(Math), { + passName: true, + pre: function(name) { + console.log("=> Math." + name, [].slice.call(arguments, 1)); + }, + post: function(result, name) { + console.log("<= Math." + name, result); + } +}); + +var result = Math.max(5, 6, 7); +// => Math.max [ 5, 6, 7 ] +// <= Math.max 7 +result // 7 + +result = Math.ceil(3.456); +// => Math.ceil [ 3.456 ] +// <= Math.ceil 4 +result // 4 +``` + +## Contributing +In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://github.com/cowboy/grunt). + +_Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!_ + +## Release History +2012/01/09 - v0.2.3 - First official release. + +## License +Copyright (c) 2012 "Cowboy" Ben Alman +Licensed under the MIT license. + diff --git a/node_modules/grunt/node_modules/hooker/child.js b/node_modules/grunt/node_modules/hooker/child.js new file mode 100644 index 000000000..ae7dcf2fa --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/child.js @@ -0,0 +1,101 @@ +var path = require('path'); +var fs = require('fs'); +var nodeunit = require('nodeunit'); + +var filepaths = fs.readdirSync('test').map(function(filename) { + return path.join('test', filename); +}); + +var unfinished = {}; +var currentModule; +function sendMessage(message) { + process.stdout.write(JSON.stringify(message) + '\n'); +} + +// If an exception is thrown, let the parent process know and exit. +process.on('uncaughtException', function (e) { + sendMessage({error: [e.name, e.message, e.stack]}); + process.exit(); +}); + +// If Nodeunit explodes because a test was missing test.done(), handle it. +var unfinished = {}; +process.on('exit', function (e) { + var len = Object.keys(unfinished).length + if (len > 0) { + sendMessage({exit: ['UNFINISHED']}); + // process.reallyExit(len); + } else { + sendMessage({exit: ['finished']}); + } + // process.exit(); +}); + +nodeunit.reporters.test = { + run: function(files, options, callback) { + // Nodeunit needs absolute paths. + var paths = files.map(function (filepath) { + return path.resolve(filepath); + }); + nodeunit.runFiles(paths, { + // No idea. + testspec: undefined, + // Executed when the first test in a file is run. If no tests exist in + // the file, this doesn't execute. + moduleStart: function(name) { + // Keep track of this so that moduleDone output can be suppressed in + // cases where a test file contains no tests. + currentModule = name; + // Send back to the parent process. + sendMessage({moduleStart: [name.toString()]}); + }, + // Executed after a file is done being processed. This executes whether + // tests exist in the file or not. + moduleDone: function(name) { + // Abort if no tests actually ran. + if (name !== currentModule) { return; } + // Send back to the parent process. + sendMessage({moduleDone: [name.toString()]}); + }, + // Executed before each test is run. + testStart: function(name) { + // Keep track of the current test, in case test.done() was omitted + // and Nodeunit explodes. + unfinished[name] = name; + // Send back to the parent process. + sendMessage({testStart: [name.toString()]}); + }, + // Executed after each test and all its assertions are run. + testDone: function(name, assertions) { + delete unfinished[name]; + // Send back to the parent process. + sendMessage({testDone: [ + name.toString(), + assertions.failures(), + assertions.map(function(assertion) { + var e = assertion.error; + if (e) { + assertion.error = { + name: e.name, + message: e.message, + stack: e.stack + }; + } + return assertion; + }) + ]}); + }, + // Executed when everything is all done. + done: function (assertions) { + // Send back to the parent process. + sendMessage({done: [ + assertions.failures(), + assertions.duration, + assertions + ]}); + } + }); + } +} + +nodeunit.reporters.test.run(filepaths, {}); diff --git a/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js b/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js new file mode 100644 index 000000000..d10a3216b --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js @@ -0,0 +1,169 @@ +/*! JavaScript Hooker - v0.2.3 - 1/29/2012 +* http://github.com/cowboy/javascript-hooker +* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ + +(function(exports) { + // Get an array from an array-like object with slice.call(arrayLikeObject). + var slice = [].slice; + // Get an "[object [[Class]]]" string with toString.call(value). + var toString = {}.toString; + + // I can't think of a better way to ensure a value is a specific type other + // than to create instances and use the `instanceof` operator. + function HookerOverride(v) { this.value = v; } + function HookerPreempt(v) { this.value = v; } + function HookerFilter(c, a) { this.context = c; this.args = a; } + + // When a pre- or post-hook returns the result of this function, the value + // passed will be used in place of the original function's return value. Any + // post-hook override value will take precedence over a pre-hook override + // value. + exports.override = function(value) { + return new HookerOverride(value); + }; + + // When a pre-hook returns the result of this function, the value passed will + // be used in place of the original function's return value, and the original + // function will NOT be executed. + exports.preempt = function(value) { + return new HookerPreempt(value); + }; + + // When a pre-hook returns the result of this function, the context and + // arguments passed will be applied into the original function. + exports.filter = function(context, args) { + return new HookerFilter(context, args); + }; + + // Execute callback(s) for properties of the specified object. + function forMethods(obj, props, callback) { + var prop; + if (typeof props === "string") { + // A single prop string was passed. Create an array. + props = [props]; + } else if (props == null) { + // No props were passed, so iterate over all properties, building an + // array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so + // this has to be done manually. + props = []; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + } + // Execute callback for every method in the props array. + var i = props.length; + while (i--) { + // If the property isn't a function... + if (toString.call(obj[props[i]]) !== "[object Function]" || + // ...or the callback returns false... + callback(obj, props[i]) === false) { + // ...remove it from the props array to be returned. + props.splice(i, 1); + } + } + // Return an array of method names for which the callback didn't fail. + return props; + } + + // Monkey-patch (hook) a method of an object. + exports.hook = function(obj, props, options) { + // If the props argument was omitted, shuffle the arguments. + if (options == null) { + options = props; + props = null; + } + // If just a function is passed instead of an options hash, use that as a + // pre-hook function. + if (typeof options === "function") { + options = {pre: options}; + } + + // Hook the specified method of the object. + return forMethods(obj, props, function(obj, prop) { + // The original (current) method. + var orig = obj[prop]; + // The new hooked function. + function hooked() { + var result, origResult, tmp; + + // Get an array of arguments. + var args = slice.call(arguments); + + // If passName option is specified, prepend prop to the args array, + // passing it as the first argument to any specified hook functions. + if (options.passName) { + args.unshift(prop); + } + + // If a pre-hook function was specified, invoke it in the current + // context with the passed-in arguments, and store its result. + if (options.pre) { + result = options.pre.apply(this, args); + } + + if (result instanceof HookerFilter) { + // If the pre-hook returned hooker.filter(context, args), invoke the + // original function with that context and arguments, and store its + // result. + origResult = result = orig.apply(result.context, result.args); + } else if (result instanceof HookerPreempt) { + // If the pre-hook returned hooker.preempt(value) just use the passed + // value and don't execute the original function. + origResult = result = result.value; + } else { + // Invoke the original function in the current context with the + // passed-in arguments, and store its result. + origResult = orig.apply(this, arguments); + // If the pre-hook returned hooker.override(value), use the passed + // value, otherwise use the original function's result. + result = result instanceof HookerOverride ? result.value : origResult; + } + + if (options.post) { + // If a post-hook function was specified, invoke it in the current + // context, passing in the result of the original function as the + // first argument, followed by any passed-in arguments. + tmp = options.post.apply(this, [origResult].concat(args)); + if (tmp instanceof HookerOverride) { + // If the post-hook returned hooker.override(value), use the passed + // value, otherwise use the previously computed result. + result = tmp.value; + } + } + + // Unhook if the "once" option was specified. + if (options.once) { + exports.unhook(obj, prop); + } + + // Return the result! + return result; + } + // Re-define the method. + obj[prop] = hooked; + // Fail if the function couldn't be hooked. + if (obj[prop] !== hooked) { return false; } + // Store a reference to the original method as a property on the new one. + obj[prop]._orig = orig; + }); + }; + + // Get a reference to the original method from a hooked function. + exports.orig = function(obj, prop) { + return obj[prop]._orig; + }; + + // Un-monkey-patch (unhook) a method of an object. + exports.unhook = function(obj, props) { + return forMethods(obj, props, function(obj, prop) { + // Get a reference to the original method, if it exists. + var orig = exports.orig(obj, prop); + // If there's no original method, it can't be unhooked, so fail. + if (!orig) { return false; } + // Unhook the method. + obj[prop] = orig; + }); + }; +}(typeof exports === "object" && exports || this)); diff --git a/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js b/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js new file mode 100644 index 000000000..2bcdb549b --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js @@ -0,0 +1,4 @@ +/*! JavaScript Hooker - v0.2.3 - 1/29/2012 +* http://github.com/cowboy/javascript-hooker +* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ +(function(a){function d(a){this.value=a}function e(a){this.value=a}function f(a,b){this.context=a,this.args=b}function g(a,b,d){var e;if(typeof b=="string")b=[b];else if(b==null){b=[];for(e in a)a.hasOwnProperty(e)&&b.push(e)}var f=b.length;while(f--)(c.call(a[b[f]])!=="[object Function]"||d(a,b[f])===!1)&&b.splice(f,1);return b}var b=[].slice,c={}.toString;a.override=function(a){return new d(a)},a.preempt=function(a){return new e(a)},a.filter=function(a,b){return new f(a,b)},a.hook=function(c,h,i){return i==null&&(i=h,h=null),typeof i=="function"&&(i={pre:i}),g(c,h,function(c,g){function j(){var j,k,l,m=b.call(arguments);return i.passName&&m.unshift(g),i.pre&&(j=i.pre.apply(this,m)),j instanceof f?k=j=h.apply(j.context,j.args):j instanceof e?k=j=j.value:(k=h.apply(this,arguments),j=j instanceof d?j.value:k),i.post&&(l=i.post.apply(this,[k].concat(m)),l instanceof d&&(j=l.value)),i.once&&a.unhook(c,g),j}var h=c[g];c[g]=j;if(c[g]!==j)return!1;c[g]._orig=h})},a.orig=function(a,b){return a[b]._orig},a.unhook=function(b,c){return g(b,c,function(b,c){var d=a.orig(b,c);if(!d)return!1;b[c]=d})}})(typeof exports=="object"&&exports||this) \ No newline at end of file diff --git a/node_modules/grunt/node_modules/hooker/grunt.js b/node_modules/grunt/node_modules/hooker/grunt.js new file mode 100644 index 000000000..c6951485a --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/grunt.js @@ -0,0 +1,47 @@ +/*global config:true, task:true*/ +config.init({ + pkg: '', + meta: { + name: 'JavaScript Hooker', + banner: '/*! <%= meta.name %> - v<%= pkg.version %> - <%= template.today("m/d/yyyy") %>\n' + + '* <%= pkg.homepage %>\n' + + '* Copyright (c) <%= template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + concat: { + 'dist/ba-hooker.js': ['', ''] + }, + min: { + 'dist/ba-hooker.min.js': ['', 'dist/ba-hooker.js'] + }, + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'lint:files test:files' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true + }, + globals: { + exports: true + } + }, + uglify: {} +}); + +// Default task. +task.registerTask('default', 'lint:files test:files concat min'); diff --git a/node_modules/grunt/node_modules/hooker/lib/hooker.js b/node_modules/grunt/node_modules/hooker/lib/hooker.js new file mode 100644 index 000000000..1ff9764b5 --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/lib/hooker.js @@ -0,0 +1,174 @@ +/* + * JavaScript Hooker + * http://github.com/cowboy/javascript-hooker + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * http://benalman.com/about/license/ + */ + +(function(exports) { + // Get an array from an array-like object with slice.call(arrayLikeObject). + var slice = [].slice; + // Get an "[object [[Class]]]" string with toString.call(value). + var toString = {}.toString; + + // I can't think of a better way to ensure a value is a specific type other + // than to create instances and use the `instanceof` operator. + function HookerOverride(v) { this.value = v; } + function HookerPreempt(v) { this.value = v; } + function HookerFilter(c, a) { this.context = c; this.args = a; } + + // When a pre- or post-hook returns the result of this function, the value + // passed will be used in place of the original function's return value. Any + // post-hook override value will take precedence over a pre-hook override + // value. + exports.override = function(value) { + return new HookerOverride(value); + }; + + // When a pre-hook returns the result of this function, the value passed will + // be used in place of the original function's return value, and the original + // function will NOT be executed. + exports.preempt = function(value) { + return new HookerPreempt(value); + }; + + // When a pre-hook returns the result of this function, the context and + // arguments passed will be applied into the original function. + exports.filter = function(context, args) { + return new HookerFilter(context, args); + }; + + // Execute callback(s) for properties of the specified object. + function forMethods(obj, props, callback) { + var prop; + if (typeof props === "string") { + // A single prop string was passed. Create an array. + props = [props]; + } else if (props == null) { + // No props were passed, so iterate over all properties, building an + // array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so + // this has to be done manually. + props = []; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + } + // Execute callback for every method in the props array. + var i = props.length; + while (i--) { + // If the property isn't a function... + if (toString.call(obj[props[i]]) !== "[object Function]" || + // ...or the callback returns false... + callback(obj, props[i]) === false) { + // ...remove it from the props array to be returned. + props.splice(i, 1); + } + } + // Return an array of method names for which the callback didn't fail. + return props; + } + + // Monkey-patch (hook) a method of an object. + exports.hook = function(obj, props, options) { + // If the props argument was omitted, shuffle the arguments. + if (options == null) { + options = props; + props = null; + } + // If just a function is passed instead of an options hash, use that as a + // pre-hook function. + if (typeof options === "function") { + options = {pre: options}; + } + + // Hook the specified method of the object. + return forMethods(obj, props, function(obj, prop) { + // The original (current) method. + var orig = obj[prop]; + // The new hooked function. + function hooked() { + var result, origResult, tmp; + + // Get an array of arguments. + var args = slice.call(arguments); + + // If passName option is specified, prepend prop to the args array, + // passing it as the first argument to any specified hook functions. + if (options.passName) { + args.unshift(prop); + } + + // If a pre-hook function was specified, invoke it in the current + // context with the passed-in arguments, and store its result. + if (options.pre) { + result = options.pre.apply(this, args); + } + + if (result instanceof HookerFilter) { + // If the pre-hook returned hooker.filter(context, args), invoke the + // original function with that context and arguments, and store its + // result. + origResult = result = orig.apply(result.context, result.args); + } else if (result instanceof HookerPreempt) { + // If the pre-hook returned hooker.preempt(value) just use the passed + // value and don't execute the original function. + origResult = result = result.value; + } else { + // Invoke the original function in the current context with the + // passed-in arguments, and store its result. + origResult = orig.apply(this, arguments); + // If the pre-hook returned hooker.override(value), use the passed + // value, otherwise use the original function's result. + result = result instanceof HookerOverride ? result.value : origResult; + } + + if (options.post) { + // If a post-hook function was specified, invoke it in the current + // context, passing in the result of the original function as the + // first argument, followed by any passed-in arguments. + tmp = options.post.apply(this, [origResult].concat(args)); + if (tmp instanceof HookerOverride) { + // If the post-hook returned hooker.override(value), use the passed + // value, otherwise use the previously computed result. + result = tmp.value; + } + } + + // Unhook if the "once" option was specified. + if (options.once) { + exports.unhook(obj, prop); + } + + // Return the result! + return result; + } + // Re-define the method. + obj[prop] = hooked; + // Fail if the function couldn't be hooked. + if (obj[prop] !== hooked) { return false; } + // Store a reference to the original method as a property on the new one. + obj[prop]._orig = orig; + }); + }; + + // Get a reference to the original method from a hooked function. + exports.orig = function(obj, prop) { + return obj[prop]._orig; + }; + + // Un-monkey-patch (unhook) a method of an object. + exports.unhook = function(obj, props) { + return forMethods(obj, props, function(obj, prop) { + // Get a reference to the original method, if it exists. + var orig = exports.orig(obj, prop); + // If there's no original method, it can't be unhooked, so fail. + if (!orig) { return false; } + // Unhook the method. + obj[prop] = orig; + }); + }; +}(typeof exports === "object" && exports || this)); diff --git a/node_modules/grunt/node_modules/hooker/package.json b/node_modules/grunt/node_modules/hooker/package.json new file mode 100644 index 000000000..2fb5fb081 --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/package.json @@ -0,0 +1,49 @@ +{ + "name": "hooker", + "description": "Monkey-patch (hook) functions for debugging and stuff.", + "version": "0.2.3", + "homepage": "http://github.com/cowboy/javascript-hooker", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/cowboy/javascript-hooker.git" + }, + "bugs": { + "url": "https://github.com/cowboy/javascript-hooker/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cowboy/javascript-hooker/blob/master/LICENSE-MIT" + } + ], + "dependencies": {}, + "devDependencies": { + "grunt": "~0.2.1" + }, + "keywords": [ + "patch", + "hook", + "function", + "debug", + "aop" + ], + "engines": { + "node": "*" + }, + "main": "lib/hooker", + "scripts": { + "test": "grunt test" + }, + "readme": "# JavaScript Hooker\n\nMonkey-patch (hook) functions for debugging and stuff.\n\n## Getting Started\n\nThis code should work just fine in Node.js:\n\nFirst, install the module with: `npm install hooker`\n\n```javascript\nvar hooker = require('hooker');\nhooker.hook(Math, \"max\", function() {\n console.log(arguments.length + \" arguments passed\");\n});\nMath.max(5, 6, 7) // logs: \"3 arguments passed\", returns 7\n```\n\nOr in the browser:\n\n```html\n\n\n```\n\nIn the browser, you can attach Hooker's methods to any object.\n\n```html\n\n\n\n```\n\n## Documentation\n\n### hooker.hook\nMonkey-patch (hook) one or more methods of an object.\n#### Signature:\n`hooker.hook(object, [ props, ] [options | prehookFunction])`\n#### `props`\nThe optional `props` argument can be a method name, array of method names or null. If null (or omitted), all enumerable methods of `object` will be hooked.\n#### `options`\n* `pre` - (Function) a pre-hook function to be executed before the original function. Arguments passed into the method will be passed into the pre-hook function as well.\n* `post` - (Function) a post-hook function to be executed after the original function. The original function's result is passed into the post-hook function as its first argument, followed by the method arguments.\n* `once` - (Boolean) if true, auto-unhook the function after the first execution.\n* `passName` - (Boolean) if true, pass the name of the method into the pre-hook function as its first arg (preceding all other arguments), and into the post-hook function as the second arg (after result but preceding all other arguments).\n\n#### Returns:\nAn array of hooked method names.\n\n### hooker.unhook\nUn-monkey-patch (unhook) one or more methods of an object.\n#### Signature:\n`hooker.unhook(object [, props ])`\n#### `props`\nThe optional `props` argument can be a method name, array of method names or null. If null (or omitted), all methods of `object` will be unhooked.\n#### Returns:\nAn array of unhooked method names.\n\n### hooker.orig\nGet a reference to the original method from a hooked function.\n#### Signature:\n`hooker.orig(object, props)`\n\n### hooker.override\nWhen a pre- or post-hook returns the result of this function, the value\npassed will be used in place of the original function's return value. Any\npost-hook override value will take precedence over a pre-hook override value.\n#### Signature:\n`hooker.override(value)`\n\n### hooker.preempt\nWhen a pre-hook returns the result of this function, the value passed will\nbe used in place of the original function's return value, and the original\nfunction will NOT be executed.\n#### Signature:\n`hooker.preempt(value)`\n\n### hooker.filter\nWhen a pre-hook returns the result of this function, the context and\narguments passed will be applied into the original function.\n#### Signature:\n`hooker.filter(context, arguments)`\n\n\n## Examples\nSee the unit tests for more examples.\n\n```javascript\nvar hooker = require('hooker');\n// Simple logging.\nhooker.hook(Math, \"max\", function() {\n console.log(arguments.length + \" arguments passed\");\n});\nMath.max(5, 6, 7) // logs: \"3 arguments passed\", returns 7\n\nhooker.unhook(Math, \"max\"); // (This is assumed between all further examples)\nMath.max(5, 6, 7) // 7\n\n// Returning hooker.override(value) overrides the original value.\nhooker.hook(Math, \"max\", function() {\n if (arguments.length === 0) {\n return hooker.override(9000);\n }\n});\nMath.max(5, 6, 7) // 7\nMath.max() // 9000\n\n// Auto-unhook after one execution.\nhooker.hook(Math, \"max\", {\n once: true,\n pre: function() {\n console.log(\"Init something here\");\n }\n});\nMath.max(5, 6, 7) // logs: \"Init something here\", returns 7\nMath.max(5, 6, 7) // 7\n\n// Filter `this` and arguments through a pre-hook function.\nhooker.hook(Math, \"max\", {\n pre: function() {\n var args = [].map.call(arguments, function(num) {\n return num * 2;\n });\n return hooker.filter(this, args); // thisValue, arguments\n }\n});\nMath.max(5, 6, 7) // 14\n\n// Modify the original function's result with a post-hook function.\nhooker.hook(Math, \"max\", {\n post: function(result) {\n return hooker.override(result * 100);\n }\n});\nMath.max(5, 6, 7) // 700\n\n// Hook every Math method. Note: if Math's methods were enumerable, the second\n// argument could be omitted. Since they aren't, an array of properties to hook\n// must be explicitly passed. Non-method properties will be skipped.\n// See a more generic example here: http://bit.ly/vvJlrS\nhooker.hook(Math, Object.getOwnPropertyNames(Math), {\n passName: true,\n pre: function(name) {\n console.log(\"=> Math.\" + name, [].slice.call(arguments, 1));\n },\n post: function(result, name) {\n console.log(\"<= Math.\" + name, result);\n }\n});\n\nvar result = Math.max(5, 6, 7);\n// => Math.max [ 5, 6, 7 ]\n// <= Math.max 7\nresult // 7\n\nresult = Math.ceil(3.456);\n// => Math.ceil [ 3.456 ]\n// <= Math.ceil 4\nresult // 4\n```\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://github.com/cowboy/grunt).\n\n_Also, please don't edit files in the \"dist\" subdirectory as they are generated via grunt. You'll find source code in the \"lib\" subdirectory!_\n\n## Release History\n2012/01/09 - v0.2.3 - First official release.\n\n## License\nCopyright (c) 2012 \"Cowboy\" Ben Alman \nLicensed under the MIT license. \n\n", + "readmeFilename": "README.md", + "_id": "hooker@0.2.3", + "dist": { + "shasum": "3b7a315240478360790c786c8af0b05bfa9b50f6" + }, + "_from": "hooker@~0.2.3", + "_resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" +} diff --git a/node_modules/grunt/node_modules/hooker/parent.js b/node_modules/grunt/node_modules/hooker/parent.js new file mode 100644 index 000000000..c4a055e65 --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/parent.js @@ -0,0 +1,17 @@ +var spawn = require('child_process').spawn; + +function loop() { + console.log('starting'); + console.log(this); + //var child = spawn('./node_modules/nodeunit/bin/nodeunit', ['test']); + var child = spawn('node', ['child.js']); + child.stdout.on('data', function(buffer) { + process.stdout.write(buffer); + }); + child.on('exit', this.async()); +} + +var context = { + async: function() { return loop.bind(context); } +}; +loop.call(context); \ No newline at end of file diff --git a/node_modules/grunt/node_modules/hooker/test/hooker_test.js b/node_modules/grunt/node_modules/hooker/test/hooker_test.js new file mode 100644 index 000000000..dc5910a4f --- /dev/null +++ b/node_modules/grunt/node_modules/hooker/test/hooker_test.js @@ -0,0 +1,435 @@ +/*global require:true */ +var hooker = require('../lib/hooker'); + +exports['hook'] = { + setUp: function(done) { + this.order = []; + this.track = function() { + [].push.apply(this.order, arguments); + }; + + this.prop = 1; + this.add = function(a, b) { + this.track("add", this.prop, a, b); + return this.prop + a + b; + }; + + this.obj = { + that: this, + prop: 1, + add1: function(a, b) { + this.that.track("add1", this.prop, a, b); + return this.prop + a + b; + }, + add2: function(a, b) { + this.that.track("add2", this.prop, a, b); + return this.prop + a + b; + }, + add3: function(a, b) { + this.that.track("add3", this.prop, a, b); + return this.prop + a + b; + } + }; + + done(); + }, + 'orig': function(test) { + test.expect(1); + var orig = this.add; + hooker.hook(this, "add", function() {}); + test.strictEqual(hooker.orig(this, "add"), orig, "should return a refernce to the original function."); + test.done(); + }, + 'once': function(test) { + test.expect(5); + var orig = this.add; + hooker.hook(this, "add", { + once: true, + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + } + }); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.strictEqual(this.add, orig, "should automatically unhook when once is specified."); + this.order = []; + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add", 1, 2, 3], "only the original function should execute."); + test.done(); + }, + 'pre-hook (simple syntax)': function(test) { + test.expect(3); + // Pre-hook. + var result = hooker.hook(this, "add", function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre-hook': function(test) { + test.expect(3); + // Pre-hook. + var result = hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + } + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'post-hook': function(test) { + test.expect(3); + // Post-hook. + var result = hooker.hook(this, "add", { + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, return value override': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // This return value will override the original function's return value. + return hooker.override("b" + this.prop + a + b); + } + }); + test.strictEqual(this.add(2, 3), "b123", "should return the overridden result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'post-hook, return value override': function(test) { + test.expect(2); + // Post-hook. + hooker.hook(this, "add", { + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1236", "should return the post-hook overridden result."); + test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // This return value will override the original function's return value. + return hooker.override("b" + this.prop + a + b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value + // AND the pre-hook's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1236", "should return the overridden result, and post-hook result should take precedence over pre-hook result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, filtering arguments': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + } + }); + test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z"], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, filtering arguments': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, filtering arguments, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value + // AND the pre-hook's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a123xyz", "should return the post-hook overridden result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, preempt original function': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(); + } + }); + test.strictEqual(this.add(2, 3), undefined, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre-hook, preempt original function with value': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + } + }); + test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, preempt original function with value': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, preempt original function with value, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override any preempt value set in pre-hook. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1239000", "should return the overridden result, and post-hook result should take precedence over preempt value."); + test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, some properties': function(test) { + test.expect(7); + // Pre- & post-hook. + var result = hooker.hook(this.obj, ["add1", "add2"], { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been hooked."); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add3", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, all properties': function(test) { + test.expect(7); + // Pre- & post-hook. + var result = hooker.hook(this.obj, { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been hooked."); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add3", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, all properties, passName': function(test) { + test.expect(6); + // Pre- & post-hook. + hooker.hook(this.obj, { + passName: true, + pre: function(name, a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, name, a, b); + }, + post: function(result, name, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, name, a, b, result); + } + }); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add1", 2, 3, "add1", 1, 2, 3, "after", 1, "add1", 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add2", 2, 3, "add2", 1, 2, 3, "after", 1, "add2", 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add3", 2, 3, "add3", 1, 2, 3, "after", 1, "add3", 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'unhook one property': function(test) { + test.expect(5); + var orig = this.add; + hooker.hook(this, "add", function() {}); + var result = hooker.unhook(this, "add"); + test.deepEqual(result, ["add"], "one function should have been unhooked."); + test.strictEqual(this.add, orig, "should have unhooked, restoring the original function"); + result = hooker.unhook(this, "add"); + test.deepEqual(result, [], "nothing should have been unhooked."); + test.strictEqual(this.add, orig, "shouldn't explode if already unhooked"); + test.strictEqual(this.add.orig, undefined, "original function shouldn't have an orig property"); + test.done(); + }, + 'unhook some properties': function(test) { + test.expect(6); + var add1 = this.obj.add1; + var add2 = this.obj.add2; + hooker.hook(this.obj, ["add1", "add2"], function() {}); + test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add3"), undefined, "should not have been hooked, so should not have an original function"); + var result = hooker.unhook(this.obj, ["add1", "add2"]); + test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been unhooked."); + test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function"); + test.done(); + }, + 'unhook all properties': function(test) { + test.expect(7); + var add1 = this.obj.add1; + var add2 = this.obj.add2; + var add3 = this.obj.add3; + hooker.hook(this.obj, function() {}); + test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add3"), add3, "should return a refernce to the original function"); + var result = hooker.unhook(this.obj); + test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been unhooked."); + test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add3, add3, "should have unhooked, restoring the original function"); + test.done(); + } +}; diff --git a/node_modules/grunt/node_modules/iconv-lite/.npmignore b/node_modules/grunt/node_modules/iconv-lite/.npmignore new file mode 100644 index 000000000..fe46877a3 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/.npmignore @@ -0,0 +1,3 @@ +node_modules +*~ +*sublime-* diff --git a/node_modules/grunt/node_modules/iconv-lite/.travis.yml b/node_modules/grunt/node_modules/iconv-lite/.travis.yml new file mode 100644 index 000000000..0bab9cd88 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/.travis.yml @@ -0,0 +1,5 @@ + language: node_js + node_js: + - 0.4 + - 0.6 + - 0.8 diff --git a/node_modules/grunt/node_modules/iconv-lite/LICENSE b/node_modules/grunt/node_modules/iconv-lite/LICENSE new file mode 100644 index 000000000..d518d8376 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2011 Alexander Shtuchkin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/node_modules/grunt/node_modules/iconv-lite/README.md b/node_modules/grunt/node_modules/iconv-lite/README.md new file mode 100644 index 000000000..ba30a32c0 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/README.md @@ -0,0 +1,72 @@ +iconv-lite - pure javascript character encoding conversion +====================================================================== + +[![Build Status](https://secure.travis-ci.org/ashtuchkin/iconv-lite.png?branch=master)](http://travis-ci.org/ashtuchkin/iconv-lite) + +## Features + +* Pure javascript. Doesn't need native code compilation. +* Easy API. +* Works on Windows and in sandboxed environments like [Cloud9](http://c9.io). +* Encoding is much faster than node-iconv (see below for performance comparison). + +## Usage + + var iconv = require('iconv-lite'); + + // Convert from an encoded buffer to string. + str = iconv.decode(buf, 'win1251'); + + // Convert from string to an encoded buffer. + buf = iconv.encode("Sample input string", 'win1251'); + + // Check if encoding is supported + iconv.encodingExists("us-ascii") + + +## Supported encodings + +* All node.js native encodings: 'utf8', 'ucs2', 'ascii', 'binary', 'base64' +* All widespread single byte encodings: Windows 125x family, ISO-8859 family, + IBM/DOS codepages, Macintosh family, KOI8 family. + Aliases like 'latin1', 'us-ascii' also supported. +* Multibyte encodings: 'gbk', 'gb2313', 'Big5', 'cp950'. + +Others are easy to add, see the source. Please, participate. +Most encodings are generated from node-iconv. Thank you Ben Noordhuis and iconv authors! + +Not supported yet: EUC family, Shift_JIS. + + +## Encoding/decoding speed + +Comparison with node-iconv module (1000x256kb, on Ubuntu 12.04, Core i5/2.5 GHz, Node v0.8.7). +Note: your results may vary, so please always check on your hardware. + + operation iconv@1.2.4 iconv-lite@0.2.4 + ---------------------------------------------------------- + encode('win1251') ~115 Mb/s ~230 Mb/s + decode('win1251') ~95 Mb/s ~130 Mb/s + + +## Notes + +When decoding, a 'binary'-encoded string can be used as a source buffer. +Untranslatable characters are set to � or ?. No transliteration is currently supported, pull requests are welcome. + +## Testing + + git clone git@github.com:ashtuchkin/iconv-lite.git + cd iconv-lite + npm install + npm test + + # To view performance: + node test/performance.js + +## TODO + +* Support streaming character conversion, something like util.pipe(req, iconv.fromEncodingStream('latin1')). +* Add more encodings. +* Add transliteration (best fit char). +* Add tests and correct support of variable-byte encodings (currently work is delegated to node). diff --git a/node_modules/grunt/node_modules/iconv-lite/README.md~ b/node_modules/grunt/node_modules/iconv-lite/README.md~ new file mode 100644 index 000000000..5f575615e --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/README.md~ @@ -0,0 +1,54 @@ +iconv-lite - native javascript conversion between character encodings. +====================================================================== + +## Usage + + var iconv = require('iconv-lite'); + + // Convert from an encoded buffer to string. + str = iconv.fromEncoding(buf, 'win-1251'); + // Or + str = iconv.decode(buf, 'win-1251'); + + // Convert from string to an encoded buffer. + buf = iconv.toEncoding("Sample input string", 'win-1251'); + // Or + buf = iconv.encode("Sample input string", 'win-1251'); + +## Supported encodings + +Currently only a small part of encodings supported: + +* All node.js native encodings: 'utf8', 'ucs2', 'ascii', 'binary', 'base64'. +* 'latin1' +* Cyrillic encodings: 'windows-1251', 'koi8-r', 'iso 8859-5'. + +Other encodings are easy to add, see the source. Please, participate. + + +## Encoding/decoding speed + +Comparison with iconv module (1000 times 256kb, on Core i5/2.5 GHz). + + Operation\module iconv iconv-lite (this) + toEncoding('win1251') 19.57 mb/s 49.04 mb/s + fromEncoding('win1251') 16.39 mb/s 24.11 mb/s + + +## Notes + +This module is JavaScript-only, thus can be used in a sandboxed environment like [Cloud9](http://c9.io). + +Untranslatable characters are set to '?'. No transliteration is currently supported, pull requests are welcome. + +## Testing + + npm install --dev iconv-lite + vows + +## TODO + +* Support streaming character conversion, something like util.pipe(req, iconv.fromEncodingStream('latin1')). +* Add more encodings. +* Add transliteration (best fit char). +* Add tests and correct support of variable-byte encodings (currently work is delegated to node). diff --git a/node_modules/grunt/node_modules/iconv-lite/encodings/big5.js b/node_modules/grunt/node_modules/iconv-lite/encodings/big5.js new file mode 100644 index 000000000..0423d63a3 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/encodings/big5.js @@ -0,0 +1,9 @@ +var big5Table = require('./table/big5.js'); +module.exports = { + 'windows950': 'big5', + 'cp950': 'big5', + 'big5': { + type: 'table', + table: big5Table + } +} diff --git a/node_modules/grunt/node_modules/iconv-lite/encodings/gbk.js b/node_modules/grunt/node_modules/iconv-lite/encodings/gbk.js new file mode 100644 index 000000000..78a63ec5e --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/encodings/gbk.js @@ -0,0 +1,9 @@ +var gbkTable = require('./table/gbk.js'); +module.exports = { + 'windows936': 'gbk', + 'gb2312': 'gbk', + 'gbk': { + type: 'table', + table: gbkTable + } +} diff --git a/node_modules/grunt/node_modules/iconv-lite/encodings/singlebyte.js b/node_modules/grunt/node_modules/iconv-lite/encodings/singlebyte.js new file mode 100644 index 000000000..f41a7ea72 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/encodings/singlebyte.js @@ -0,0 +1,340 @@ +module.exports = { + "437": "cp437", + "737": "cp737", + "775": "cp775", + "850": "cp850", + "852": "cp852", + "855": "cp855", + "857": "cp857", + "858": "cp858", + "860": "cp860", + "861": "cp861", + "862": "cp862", + "863": "cp863", + "864": "cp864", + "865": "cp865", + "866": "cp866", + "869": "cp869", + "874": "iso885911", + "1250": "windows1250", + "1251": "windows1251", + "1252": "windows1252", + "1253": "windows1253", + "1254": "windows1254", + "1255": "windows1255", + "1256": "windows1256", + "1257": "windows1257", + "1258": "windows1258", + "10000": "macroman", + "10006": "macgreek", + "10007": "maccyrillic", + "10029": "maccenteuro", + "10079": "maciceland", + "10081": "macturkish", + "20866": "koi8r", + "21866": "koi8u", + "28591": "iso88591", + "28592": "iso88592", + "28593": "iso88593", + "28594": "iso88594", + "28595": "iso88595", + "28596": "iso88596", + "28597": "iso88597", + "28598": "iso88598", + "28599": "iso88599", + "28600": "iso885910", + "28601": "iso885911", + "28603": "iso885913", + "28604": "iso885914", + "28605": "iso885915", + "28606": "iso885916", + "ascii8bit": "ascii", + "usascii": "ascii", + "latin1": "iso88591", + "latin2": "iso88592", + "latin3": "iso88593", + "latin4": "iso88594", + "latin6": "iso885910", + "latin7": "iso885913", + "latin8": "iso885914", + "latin9": "iso885915", + "latin10": "iso885916", + "cp819": "iso88951", + "arabic": "iso88596", + "arabic8": "iso88596", + "greek": "iso88597", + "greek8": "iso88597", + "hebrew": "iso88598", + "hebrew8": "iso88598", + "turkish": "iso88599", + "turkish8": "iso88599", + "thai": "iso885911", + "thai8": "iso885911", + "tis620": "iso885911", + "windows874": "iso885911", + "win874": "iso885911", + "cp874": "iso885911", + "celtic": "iso885914", + "celtic8": "iso885914", + "cp20866": "koi8r", + "ibm878": "koi8r", + "cp21866": "koi8u", + "ibm1168": "koi8u", + "windows1250": { + "type": "singlebyte", + "chars": "€�‚�„…†‡�‰Š‹ŚŤŽŹ�‘’“”•–—�™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙" + }, + "win1250": "windows1250", + "cp1250": "windows1250", + "windows1251": { + "type": "singlebyte", + "chars": "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—�™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя" + }, + "win1251": "windows1251", + "cp1251": "windows1251", + "windows1252": { + "type": "singlebyte", + "chars": "€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "win1252": "windows1252", + "cp1252": "windows1252", + "windows1253": { + "type": "singlebyte", + "chars": "€�‚ƒ„…†‡�‰�‹�����‘’“”•–—�™�›���� ΅Ά£¤¥¦§¨©�«¬­®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�" + }, + "win1253": "windows1253", + "cp1253": "windows1253", + "windows1254": { + "type": "singlebyte", + "chars": "€�‚ƒ„…†‡ˆ‰Š‹Œ����‘’“”•–—˜™š›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ" + }, + "win1254": "windows1254", + "cp1254": "windows1254", + "windows1255": { + "type": "singlebyte", + "chars": "€�‚ƒ„…†‡ˆ‰�‹�����‘’“”•–—˜™�›���� ¡¢£₪¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹ�ֻּֽ־ֿ׀ׁׂ׃װױײ׳״�������אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�" + }, + "win1255": "windows1255", + "cp1255": "windows1255", + "windows1256": { + "type": "singlebyte", + "chars": "€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ‌‍ں ،¢£¤¥¦§¨©ھ«¬­®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûü‎‏ے" + }, + "win1256": "windows1256", + "cp1256": "windows1256", + "windows1257": { + "type": "singlebyte", + "chars": "€�‚�„…†‡�‰�‹�¨ˇ¸�‘’“”•–—�™�›�¯˛� �¢£¤�¦§Ø©Ŗ«¬­®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙" + }, + "win1257": "windows1257", + "cp1257": "windows1257", + "windows1258": { + "type": "singlebyte", + "chars": "€�‚ƒ„…†‡ˆ‰�‹Œ����‘’“”•–—˜™�›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ" + }, + "win1258": "windows1258", + "cp1258": "windows1258", + "iso88591": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "cp28591": "iso88591", + "iso88592": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ą˘Ł¤ĽŚ§¨ŠŞŤŹ­ŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙" + }, + "cp28592": "iso88592", + "iso88593": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ħ˘£¤�Ĥ§¨İŞĞĴ­�Ż°ħ²³´µĥ·¸ışğĵ½�żÀÁÂ�ÄĊĈÇÈÉÊËÌÍÎÏ�ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ�äċĉçèéêëìíîï�ñòóôġö÷ĝùúûüŭŝ˙" + }, + "cp28593": "iso88593", + "iso88594": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĸŖ¤ĨĻ§¨ŠĒĢŦ­Ž¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙" + }, + "cp28594": "iso88594", + "iso88595": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ" + }, + "cp28595": "iso88595", + "iso88596": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ���¤�������،­�������������؛���؟�ءآأؤإئابةتثجحخدذرزسشصضطظعغ�����ـفقكلمنهوىيًٌٍَُِّْ�������������" + }, + "cp28596": "iso88596", + "iso88597": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­�―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�" + }, + "cp28597": "iso88597", + "iso88598": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �¢£¤¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾��������������������������������‗אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�" + }, + "cp28598": "iso88598", + "iso88599": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ" + }, + "cp28599": "iso88599", + "iso885910": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĒĢĪĨĶ§ĻĐŠŦŽ­ŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ" + }, + "cp28600": "iso885910", + "iso885911": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����" + }, + "cp28601": "iso885911", + "iso885913": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’" + }, + "cp28603": "iso885913", + "iso885914": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ­®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ" + }, + "cp28604": "iso885914", + "iso885915": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥Š§š©ª«¬­®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "cp28605": "iso885915", + "iso885916": { + "type": "singlebyte", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄąŁ€„Š§š©Ș«Ź­źŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ" + }, + "cp28606": "iso885916", + "cp437": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm437": "cp437", + "cp737": { + "type": "singlebyte", + "chars": "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρσςτυφχψ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ωάέήϊίόύϋώΆΈΉΊΌΎΏ±≥≤ΪΫ÷≈°∙·√ⁿ²■ " + }, + "ibm737": "cp737", + "cp775": { + "type": "singlebyte", + "chars": "ĆüéāäģåćłēŖŗīŹÄÅÉæÆōöĢ¢ŚśÖÜø£ØפĀĪóŻżź”¦©®¬½¼Ł«»░▒▓│┤ĄČĘĖ╣║╗╝ĮŠ┐└┴┬├─┼ŲŪ╚╔╩╦╠═╬Žąčęėįšųūž┘┌█▄▌▐▀ÓßŌŃõÕµńĶķĻļņĒŅ’­±“¾¶§÷„°∙·¹³²■ " + }, + "ibm775": "cp775", + "cp850": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈıÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ " + }, + "ibm850": "cp850", + "cp852": { + "type": "singlebyte", + "chars": "ÇüéâäůćçłëŐőîŹÄĆÉĹĺôöĽľŚśÖÜŤťŁ×čáíóúĄąŽžĘ꬟Ⱥ«»░▒▓│┤ÁÂĚŞ╣║╗╝Żż┐└┴┬├─┼Ăă╚╔╩╦╠═╬¤đĐĎËďŇÍÎě┘┌█▄ŢŮ▀ÓßÔŃńňŠšŔÚŕŰýÝţ´­˝˛ˇ˘§÷¸°¨˙űŘř■ " + }, + "ibm852": "cp852", + "cp855": { + "type": "singlebyte", + "chars": "ђЂѓЃёЁєЄѕЅіІїЇјЈљЉњЊћЋќЌўЎџЏюЮъЪаАбБцЦдДеЕфФгГ«»░▒▓│┤хХиИ╣║╗╝йЙ┐└┴┬├─┼кК╚╔╩╦╠═╬¤лЛмМнНоОп┘┌█▄Пя▀ЯрРсСтТуУжЖвВьЬ№­ыЫзЗшШэЭщЩчЧ§■ " + }, + "ibm855": "cp855", + "cp857": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèïîıÄÅÉæÆôöòûùİÖÜø£ØŞşáíóúñÑĞ𿮬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ºªÊËÈ�ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµ�×ÚÛÙìÿ¯´­±�¾¶§÷¸°¨·¹³²■ " + }, + "ibm857": "cp857", + "cp858": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ " + }, + "ibm858": "cp858", + "cp860": { + "type": "singlebyte", + "chars": "ÇüéâãàÁçêÊèÍÔìÃÂÉÀÈôõòÚùÌÕÜ¢£Ù₧ÓáíóúñѪº¿Ò¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm860": "cp860", + "cp861": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèÐðÞÄÅÉæÆôöþûÝýÖÜø£Ø₧ƒáíóúÁÍÓÚ¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm861": "cp861", + "cp862": { + "type": "singlebyte", + "chars": "אבגדהוזחטיךכלםמןנסעףפץצקרשת¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm862": "cp862", + "cp863": { + "type": "singlebyte", + "chars": "ÇüéâÂà¶çêëèïî‗À§ÉÈÊôËÏûù¤ÔÜ¢£ÙÛƒ¦´óú¨¸³¯Î⌐¬½¼¾«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm863": "cp863", + "cp864": { + "type": "singlebyte", + "chars": "°·∙√▒─│┼┤┬├┴┐┌└┘β∞φ±½¼≈«»ﻷﻸ��ﻻﻼ� ­ﺂ£¤ﺄ��ﺎﺏﺕﺙ،ﺝﺡﺥ٠١٢٣٤٥٦٧٨٩ﻑ؛ﺱﺵﺹ؟¢ﺀﺁﺃﺅﻊﺋﺍﺑﺓﺗﺛﺟﺣﺧﺩﺫﺭﺯﺳﺷﺻﺿﻁﻅﻋﻏ¦¬÷×ﻉـﻓﻗﻛﻟﻣﻧﻫﻭﻯﻳﺽﻌﻎﻍﻡﹽّﻥﻩﻬﻰﻲﻐﻕﻵﻶﻝﻙﻱ■�" + }, + "ibm864": "cp864", + "cp865": { + "type": "singlebyte", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø₧ƒáíóúñѪº¿⌐¬½¼¡«¤░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm865": "cp865", + "cp866": { + "type": "singlebyte", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ " + }, + "ibm866": "cp866", + "cp869": { + "type": "singlebyte", + "chars": "������Ά�·¬¦‘’Έ―ΉΊΪΌ��ΎΫ©Ώ²³ά£έήίϊΐόύΑΒΓΔΕΖΗ½ΘΙ«»░▒▓│┤ΚΛΜΝ╣║╗╝ΞΟ┐└┴┬├─┼ΠΡ╚╔╩╦╠═╬ΣΤΥΦΧΨΩαβγ┘┌█▄δε▀ζηθικλμνξοπρσςτ΄­±υφχ§ψ΅°¨ωϋΰώ■ " + }, + "ibm869": "cp869", + "maccenteuro": { + "type": "singlebyte", + "chars": "ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ" + }, + "maccroatian": { + "type": "singlebyte", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊�©⁄¤‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ" + }, + "maccyrillic": { + "type": "singlebyte", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°¢£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµ∂ЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤" + }, + "macgreek": { + "type": "singlebyte", + "chars": "Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦­ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ�" + }, + "maciceland": { + "type": "singlebyte", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macroman": { + "type": "singlebyte", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macromania": { + "type": "singlebyte", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂŞ∞±≤≥¥µ∂∑∏π∫ªºΩăş¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›Ţţ‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macthai": { + "type": "singlebyte", + "chars": "«»…“”�•‘’� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู​–—฿เแโใไๅๆ็่้๊๋์ํ™๏๐๑๒๓๔๕๖๗๘๙®©����" + }, + "macturkish": { + "type": "singlebyte", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙ�ˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macukraine": { + "type": "singlebyte", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤" + }, + "koi8r": { + "type": "singlebyte", + "chars": "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + }, + "koi8u": { + "type": "singlebyte", + "chars": "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґ╝╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪Ґ╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + } +}; diff --git a/node_modules/grunt/node_modules/iconv-lite/encodings/table/big5.js b/node_modules/grunt/node_modules/iconv-lite/encodings/table/big5.js new file mode 100644 index 000000000..605c72d3e --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/encodings/table/big5.js @@ -0,0 +1 @@ +module.exports={"33088":19991,"33089":20002,"33090":20012,"33091":20053,"33092":20066,"33093":20106,"33094":20144,"33095":20203,"33096":20205,"33097":20220,"33098":20252,"33099":20362,"33100":20479,"33101":20546,"33102":20560,"33103":20600,"33104":20696,"33105":20702,"33106":20724,"33107":20758,"33108":20810,"33109":20817,"33110":20836,"33111":20842,"33112":20869,"33113":20880,"33114":20893,"33115":20902,"33116":20904,"33117":20905,"33118":20935,"33119":20950,"33120":20955,"33121":20972,"33122":20988,"33123":21003,"33124":21012,"33125":21013,"33126":21024,"33127":21035,"33128":21049,"33129":21071,"33130":21105,"33131":21136,"33132":21138,"33133":21140,"33134":21148,"33135":21167,"33136":21173,"33137":21200,"33138":21248,"33139":21255,"33140":21284,"33141":21318,"33142":21343,"33143":21395,"33144":21424,"33145":21469,"33146":21539,"33147":21584,"33148":21585,"33149":21642,"33150":21661,"33185":21667,"33186":21684,"33187":21712,"33188":21795,"33189":21823,"33190":21836,"33191":21843,"33192":21853,"33193":21868,"33194":21918,"33195":21929,"33196":21996,"33197":22005,"33198":22051,"33199":22096,"33200":22140,"33201":22154,"33202":22164,"33203":22176,"33204":22191,"33205":22232,"33206":22272,"33207":22361,"33208":22373,"33209":22399,"33210":22405,"33211":22409,"33212":22433,"33213":22444,"33214":22452,"33215":22464,"33216":22472,"33217":22483,"33218":22511,"33219":22596,"33220":22636,"33221":22674,"33222":22682,"33223":22706,"33224":22712,"33225":22757,"33226":22779,"33227":22786,"33228":22795,"33229":22800,"33230":22808,"33231":22811,"33232":29836,"33233":29837,"33234":29849,"33235":29851,"33236":29860,"33237":29876,"33238":29881,"33239":29896,"33240":29900,"33241":29904,"33242":29907,"33243":30018,"33244":30037,"33245":30062,"33246":30093,"33247":30110,"33248":30172,"33249":30252,"33250":30287,"33251":30289,"33252":30323,"33253":30324,"33254":30373,"33255":30425,"33256":30478,"33257":30479,"33258":30552,"33259":30578,"33260":30583,"33261":30584,"33262":30586,"33263":30587,"33264":30616,"33265":30639,"33266":30654,"33267":30659,"33268":30661,"33269":30667,"33270":30685,"33271":30694,"33272":30708,"33273":30750,"33274":30781,"33275":30786,"33276":30788,"33277":30795,"33278":30801,"33344":21782,"33345":22775,"33346":38964,"33347":33883,"33348":28948,"33349":33398,"33350":35158,"33351":40236,"33352":40206,"33353":36527,"33354":24674,"33355":26214,"33356":34510,"33357":25785,"33358":37772,"33359":22107,"33360":28485,"33361":35532,"33362":29001,"33363":24012,"33364":34633,"33365":39464,"33366":31658,"33367":36107,"33368":39255,"33369":23597,"33370":32331,"33371":38938,"33372":20518,"33373":25458,"33374":40568,"33375":30783,"33376":40633,"33377":40634,"33378":36046,"33379":35715,"33380":61305,"33381":33931,"33382":37284,"33383":31331,"33384":25776,"33385":24061,"33386":24214,"33387":32865,"33388":26965,"33389":31466,"33390":28710,"33391":26812,"33392":31095,"33393":28060,"33394":36841,"33395":31074,"33396":22178,"33397":34687,"33398":21093,"33399":31108,"33400":28300,"33401":37271,"33402":31622,"33403":38956,"33404":26717,"33405":20397,"33406":34222,"33441":31725,"33442":34635,"33443":20534,"33444":26893,"33445":27542,"33446":24910,"33447":20855,"33448":30495,"33449":20516,"33450":32622,"33451":30452,"33452":27097,"33453":24803,"33454":25334,"33455":21599,"33456":38788,"33457":22092,"33458":20677,"33459":22040,"33460":34398,"33461":22834,"33462":22875,"33463":22877,"33464":22883,"33465":22892,"33466":22939,"33467":22999,"33468":23019,"33469":23066,"33470":23210,"33471":23248,"33472":23281,"33473":23350,"33474":23497,"33475":23539,"33476":23571,"33477":23580,"33478":23582,"33479":23635,"33480":23705,"33481":23708,"33482":23738,"33483":23739,"33484":23745,"33485":23797,"33486":23802,"33487":23829,"33488":23832,"33489":23870,"33490":23891,"33491":23900,"33492":23917,"33493":23923,"33494":23924,"33495":23948,"33496":23952,"33497":23993,"33498":24016,"33499":24019,"33500":24135,"33501":24164,"33502":24271,"33503":24272,"33504":24298,"33505":24304,"33506":24329,"33507":24332,"33508":24337,"33509":24353,"33510":24372,"33511":24385,"33512":24389,"33513":24401,"33514":24412,"33515":24422,"33516":24451,"33517":24560,"33518":24650,"33519":24672,"33520":24715,"33521":24742,"33522":24798,"33523":24849,"33524":24864,"33525":24865,"33526":24892,"33527":24893,"33528":24984,"33529":25015,"33530":25076,"33531":25107,"33532":25117,"33533":25118,"33534":25143,"33600":24186,"33601":27664,"33602":21454,"33603":20267,"33604":20302,"33605":21556,"33606":22257,"33607":22766,"33608":22841,"33609":22918,"33610":23596,"33611":20915,"33612":20914,"33613":28798,"33614":35265,"33615":35282,"33616":36125,"33617":36710,"33618":20122,"33619":26469,"33620":20177,"33621":20004,"33622":21327,"33623":23626,"33624":20872,"33625":24213,"33626":25269,"33627":19996,"33628":20105,"33629":29366,"33630":31868,"33631":32416,"33632":21351,"33633":36711,"33634":37048,"33635":38271,"33636":38376,"33637":20384,"33638":20387,"33639":20822,"33640":21017,"33641":21170,"33642":21364,"33643":22850,"33644":24069,"33645":26594,"33646":27769,"33647":20026,"33648":32419,"33649":32418,"33650":32426,"33651":32427,"33652":32421,"33653":32422,"33654":32417,"33655":32989,"33656":33486,"33657":35745,"33658":35746,"33659":35747,"33660":36126,"33661":36127,"33662":20891,"33697":36712,"33698":38377,"33699":38886,"33700":39029,"33701":39118,"33702":39134,"33703":20457,"33704":20204,"33705":20261,"33706":20010,"33707":20262,"33708":20179,"33709":20923,"33710":21018,"33711":21093,"33712":21592,"33713":23089,"33714":23385,"33715":23777,"33716":23707,"33717":23704,"33718":24072,"33719":24211,"33720":24452,"33721":25375,"33722":26102,"33723":26187,"33724":20070,"33725":27902,"33726":27971,"33727":20044,"33728":29421,"33729":29384,"33730":20137,"33731":30757,"33732":31210,"33733":32442,"33734":32433,"33735":32441,"33736":32431,"33737":32445,"33738":32432,"33739":32423,"33740":32429,"33741":32435,"33742":32440,"33743":32439,"33744":32961,"33745":33033,"33746":21005,"33747":35760,"33748":35750,"33749":35752,"33750":35751,"33751":35754,"33752":35759,"33753":35757,"33754":35755,"33755":23682,"33756":36130,"33757":36129,"33758":36713,"33759":36715,"33760":38025,"33761":38024,"33762":38026,"33763":38027,"33764":38378,"33765":38453,"33766":38485,"33767":38473,"33768":39269,"33769":39532,"33770":39592,"33771":20266,"33772":20255,"33773":20390,"33774":20391,"33775":21153,"33776":21160,"33777":21306,"33778":21442,"33779":21713,"33780":38382,"33781":34900,"33782":22269,"33783":22362,"33784":22441,"33785":25191,"33786":22815,"33787":23044,"33788":22919,"33789":19987,"33790":23558,"33856":23625,"33857":23781,"33858":23703,"33859":24102,"33860":24080,"33861":24352,"33862":24378,"33863":20174,"33864":24469,"33865":20932,"33866":24581,"33867":25195,"33868":25346,"33869":25194,"33870":25249,"33871":25379,"33872":36133,"33873":21551,"33874":26011,"33875":26025,"33876":26172,"33877":21206,"33878":24323,"33879":26465,"33880":26541,"33881":26432,"33882":27682,"33883":20937,"33884":27973,"33885":28170,"33886":27882,"33887":27814,"33888":20928,"33889":29301,"33890":29424,"33891":29616,"33892":20135,"33893":27605,"33894":24322,"33895":20247,"33896":32458,"33897":32479,"33898":32461,"33899":32459,"33900":32460,"33901":32454,"33902":32453,"33903":32452,"33904":32456,"33905":32449,"33906":32450,"33907":38069,"33908":20064,"33909":33626,"33910":33550,"33911":33682,"33912":24196,"33913":33483,"33914":22788,"33915":26415,"33916":34926,"33917":35269,"33918":35268,"33953":35775,"33954":35766,"33955":35776,"33956":35767,"33957":35768,"33958":35774,"33959":35772,"33960":35769,"33961":36137,"33962":36131,"33963":36143,"33964":36135,"33965":36138,"33966":36139,"33967":36717,"33968":36719,"33969":36825,"33970":36830,"33971":36851,"33972":38039,"33973":38035,"33974":38031,"33975":38034,"33976":38381,"33977":38472,"33978":38470,"33979":38452,"33980":39030,"33981":39031,"33982":40060,"33983":40479,"33984":21348,"33985":40614,"33986":22791,"33987":20263,"33988":20254,"33989":20975,"33990":21056,"33991":21019,"33992":21171,"33993":21195,"33994":20007,"33995":21333,"33996":21727,"33997":21796,"33998":20052,"33999":22260,"34000":23591,"34001":22330,"34002":25253,"34003":22490,"34004":22774,"34005":23090,"34006":23547,"34007":23706,"34008":24103,"34009":24079,"34010":21397,"34011":21417,"34012":24694,"34013":38391,"34014":24812,"34015":24699,"34016":24700,"34017":25315,"34018":25381,"34019":25442,"34020":25196,"34021":26531,"34022":26635,"34023":26632,"34024":38054,"34025":27531,"34026":22771,"34027":27695,"34028":27689,"34029":28044,"34030":20945,"34031":28270,"34032":28065,"34033":27748,"34034":27979,"34035":27985,"34036":28067,"34037":26080,"34038":29369,"34039":33487,"34040":30011,"34041":30153,"34042":21457,"34043":30423,"34044":30746,"34045":31174,"34046":31383,"34112":31508,"34113":31499,"34114":32478,"34115":32467,"34116":32466,"34117":32477,"34118":19997,"34119":32476,"34120":32473,"34121":32474,"34122":32470,"34123":32475,"34124":32899,"34125":32958,"34126":32960,"34127":21326,"34128":33713,"34129":33484,"34130":34394,"34131":35270,"34132":35780,"34133":35789,"34134":35777,"34135":35778,"34136":35791,"34137":35781,"34138":35784,"34139":35787,"34140":35785,"34141":35786,"34142":35779,"34143":36142,"34144":36148,"34145":36144,"34146":36155,"34147":36146,"34148":36153,"34149":36154,"34150":36149,"34151":20080,"34152":36140,"34153":36152,"34154":36151,"34155":36722,"34156":36724,"34157":36726,"34158":36827,"34159":37038,"34160":20065,"34161":38046,"34162":38062,"34163":38041,"34164":38048,"34165":38055,"34166":38045,"34167":38052,"34168":38051,"34169":38389,"34170":38384,"34171":24320,"34172":38386,"34173":38388,"34174":38387,"34209":38431,"34210":38454,"34211":38451,"34212":38887,"34213":39033,"34214":39034,"34215":39035,"34216":39274,"34217":39277,"34218":39272,"34219":39278,"34220":39276,"34221":20911,"34222":39533,"34223":20081,"34224":20538,"34225":20256,"34226":20165,"34227":20542,"34228":20260,"34229":20588,"34230":38130,"34231":21183,"34232":31215,"34233":27719,"34234":21527,"34235":21596,"34236":21595,"34237":22253,"34238":22278,"34239":28034,"34240":22359,"34241":22366,"34242":22488,"34243":33556,"34244":22885,"34245":22920,"34246":29233,"34247":24574,"34248":24582,"34249":24698,"34250":25439,"34251":25250,"34252":25443,"34253":26500,"34254":26198,"34255":26197,"34256":26104,"34257":20250,"34258":19994,"34259":26497,"34260":26472,"34261":26722,"34262":26539,"34263":23681,"34264":27807,"34265":28781,"34266":28287,"34267":28369,"34268":27815,"34269":28902,"34270":28860,"34271":28800,"34272":28949,"34273":29239,"34274":29422,"34275":29502,"34276":29682,"34277":24403,"34278":30415,"34279":30544,"34280":30529,"34281":38606,"34282":30860,"34283":33410,"34284":31509,"34285":31908,"34286":32463,"34287":32482,"34288":32465,"34289":32485,"34290":32486,"34291":20041,"34292":32673,"34293":22307,"34294":32928,"34295":33050,"34296":32959,"34297":33041,"34298":33636,"34299":33479,"34300":21494,"34301":33716,"34302":34398,"34368":34383,"34369":21495,"34370":34568,"34371":34476,"34372":34917,"34373":35013,"34374":35815,"34375":35813,"34376":35814,"34377":35797,"34378":35799,"34379":35800,"34380":35801,"34381":35811,"34382":35802,"34383":35805,"34384":35803,"34385":35809,"34386":35810,"34387":35808,"34388":35807,"34389":36156,"34390":36164,"34391":36158,"34392":36159,"34393":36160,"34394":36161,"34395":36162,"34396":36165,"34397":36739,"34398":36733,"34399":36732,"34400":36734,"34401":20892,"34402":36816,"34403":36798,"34404":36829,"34405":36807,"34406":37049,"34407":38068,"34408":38067,"34409":38073,"34410":38072,"34411":38078,"34412":38080,"34413":38085,"34414":38057,"34415":38082,"34416":38083,"34417":38089,"34418":38091,"34419":38044,"34420":38093,"34421":38079,"34422":38086,"34423":38392,"34424":38504,"34425":38589,"34426":30005,"34427":39044,"34428":39037,"34429":39039,"34430":39036,"34465":39041,"34466":39042,"34467":39282,"34468":39284,"34469":39281,"34470":39280,"34471":39536,"34472":39534,"34473":39535,"34474":40480,"34475":20389,"34476":20392,"34477":21294,"34478":21388,"34479":23581,"34480":21589,"34481":21497,"34482":21949,"34483":21863,"34484":21716,"34485":22242,"34486":22270,"34487":23576,"34488":22443,"34489":22545,"34490":23551,"34491":26790,"34492":22842,"34493":22849,"34494":22954,"34495":23454,"34496":23517,"34497":23545,"34498":23649,"34499":23853,"34500":23702,"34501":24065,"34502":24124,"34503":24443,"34504":24577,"34505":24815,"34506":24696,"34507":24813,"34508":24808,"34509":25602,"34510":25524,"34511":25530,"34512":30021,"34513":33635,"34514":26538,"34515":28378,"34516":28173,"34517":27721,"34518":28385,"34519":28382,"34520":28176,"34521":28072,"34522":28063,"34523":27818,"34524":28180,"34525":28183,"34526":28068,"34527":33639,"34528":23572,"34529":33638,"34530":29425,"34531":29712,"34532":29595,"34533":30111,"34534":30113,"34535":30127,"34536":30186,"34537":23613,"34538":30417,"34539":30805,"34540":31087,"34541":31096,"34542":31181,"34543":31216,"34544":27964,"34545":31389,"34546":31546,"34547":31581,"34548":32509,"34549":32510,"34550":32508,"34551":32496,"34552":32491,"34553":32511,"34554":32039,"34555":32512,"34556":32434,"34557":32494,"34558":32504,"34624":32501,"34625":32438,"34626":32500,"34627":32490,"34628":32513,"34629":32502,"34630":32602,"34631":38395,"34632":33669,"34633":30422,"34634":33642,"34635":33485,"34636":34432,"34637":35829,"34638":35821,"34639":35820,"34640":35748,"34641":35819,"34642":35823,"34643":35828,"34644":35824,"34645":35826,"34646":35825,"34647":35827,"34648":35822,"34649":23486,"34650":36168,"34651":36170,"34652":36213,"34653":36214,"34654":36741,"34655":36740,"34656":36731,"34657":36828,"34658":36874,"34659":36882,"34660":38128,"34661":38134,"34662":38108,"34663":38125,"34664":38114,"34665":38124,"34666":38120,"34667":38133,"34668":38115,"34669":38402,"34670":38394,"34671":38397,"34672":38401,"34673":38400,"34674":38469,"34675":39047,"34676":39046,"34677":39122,"34678":39290,"34679":39292,"34680":39285,"34681":39287,"34682":39539,"34683":32942,"34684":39600,"34685":40483,"34686":40482,"34721":20964,"34722":40784,"34723":20159,"34724":20202,"34725":20215,"34726":20396,"34727":20393,"34728":20461,"34729":21095,"34730":21016,"34731":21073,"34732":21053,"34733":21385,"34734":21792,"34735":22068,"34736":21719,"34737":22040,"34738":21943,"34739":21880,"34740":21501,"34741":22687,"34742":22367,"34743":22368,"34744":22549,"34745":23092,"34746":23157,"34747":22953,"34748":23047,"34749":23046,"34750":23485,"34751":23457,"34752":20889,"34753":23618,"34754":23956,"34755":24092,"34756":24223,"34757":21416,"34758":24217,"34759":21422,"34760":24191,"34761":24377,"34762":24198,"34763":34385,"34764":24551,"34765":24578,"34766":24751,"34767":24814,"34768":24868,"34769":24579,"34770":25370,"34771":25169,"34772":25438,"34773":25320,"34774":25376,"34775":25242,"34776":25528,"34777":25599,"34778":25932,"34779":25968,"34780":26242,"34781":26165,"34782":26679,"34783":26729,"34784":26530,"34785":26631,"34786":27004,"34787":26728,"34788":20048,"34789":26526,"34790":27431,"34791":27527,"34792":27572,"34793":27974,"34794":27900,"34795":27905,"34796":27975,"34797":28291,"34798":28070,"34799":28071,"34800":27988,"34801":28909,"34802":22870,"34803":33721,"34804":30126,"34805":30353,"34806":30385,"34807":30424,"34808":30830,"34809":30721,"34810":31377,"34811":31351,"34812":32532,"34813":32451,"34814":32428,"34880":32516,"34881":32517,"34882":32521,"34883":32534,"34884":32536,"34885":32447,"34886":32526,"34887":32531,"34888":32525,"34889":32514,"34890":32520,"34891":32519,"34892":39554,"34893":32610,"34894":33014,"34895":32932,"34896":33714,"34897":33643,"34898":33931,"34899":34430,"34900":34583,"34901":21355,"34902":35850,"34903":35845,"34904":35848,"34905":35846,"34906":35806,"34907":35831,"34908":35832,"34909":35838,"34910":35839,"34911":35844,"34912":35843,"34913":35841,"34914":35770,"34915":35812,"34916":35847,"34917":35837,"34918":35840,"34919":31446,"34920":36180,"34921":36175,"34922":36171,"34923":36145,"34924":36134,"34925":36172,"34926":36132,"34927":21334,"34928":36176,"34929":36136,"34930":36179,"34931":36341,"34932":36745,"34933":36742,"34934":36749,"34935":36744,"34936":36743,"34937":36718,"34938":36750,"34939":36747,"34940":36746,"34941":36866,"34942":36801,"34977":37051,"34978":37073,"34979":37011,"34980":38156,"34981":38161,"34982":38144,"34983":38138,"34984":38096,"34985":38148,"34986":38109,"34987":38160,"34988":38153,"34989":38155,"34990":38049,"34991":38146,"34992":38398,"34993":38405,"34994":24041,"34995":39049,"34996":39052,"34997":20859,"34998":39295,"34999":39297,"35000":39548,"35001":39547,"35002":39543,"35003":39542,"35004":39549,"35005":39550,"35006":39545,"35007":39544,"35008":39607,"35009":38393,"35010":40063,"35011":40065,"35012":40489,"35013":40486,"35014":40632,"35015":40831,"35016":20454,"35017":20647,"35018":20394,"35019":24130,"35020":21058,"35021":21544,"35022":21725,"35023":22003,"35024":22438,"35025":22363,"35026":22859,"35027":34949,"35028":23398,"35029":23548,"35030":23466,"35031":20973,"35032":24811,"35033":25044,"35034":24518,"35035":25112,"35036":25317,"35037":25377,"35038":25374,"35039":25454,"35040":25523,"35041":25321,"35042":25441,"35043":25285,"35044":25373,"35045":21382,"35046":26195,"35047":26196,"35048":26137,"35049":26726,"35050":27178,"35051":26641,"35052":26925,"35053":26725,"35054":26426,"35055":26721,"35056":28096,"35057":27987,"35058":27901,"35059":27978,"35060":27811,"35061":28582,"35062":28177,"35063":28861,"35064":28903,"35065":28783,"35066":28907,"35067":28950,"35068":29420,"35069":29585,"35070":29935,"35136":30232,"35137":21346,"35138":30610,"35139":30742,"35140":30875,"35141":31215,"35142":39062,"35143":31267,"35144":31397,"35145":31491,"35146":31579,"35147":32546,"35148":32547,"35149":33830,"35150":32538,"35151":21439,"35152":32543,"35153":32540,"35154":32537,"35155":32457,"35156":33147,"35157":20852,"35158":33329,"35159":33633,"35160":33831,"35161":33436,"35162":34434,"35163":33828,"35164":35044,"35165":20146,"35166":35278,"35167":35867,"35168":35866,"35169":35855,"35170":35763,"35171":35851,"35172":35853,"35173":35856,"35174":35864,"35175":35834,"35176":35858,"35177":35859,"35178":35773,"35179":35861,"35180":35865,"35181":35852,"35182":35862,"35183":36182,"35184":36752,"35185":36753,"35186":36755,"35187":36751,"35188":21150,"35189":36873,"35190":36831,"35191":36797,"35192":36951,"35193":37050,"35194":38189,"35195":38191,"35196":38192,"35197":38169,"35198":38065,"35233":38050,"35234":38177,"35235":24405,"35236":38126,"35237":38181,"35238":38182,"35239":38175,"35240":38178,"35241":38193,"35242":38414,"35243":38543,"35244":38505,"35245":38745,"35246":33148,"35247":39050,"35248":39048,"35249":39057,"35250":39060,"35251":22836,"35252":39059,"35253":39056,"35254":39302,"35255":39279,"35256":39300,"35257":39301,"35258":39559,"35259":39560,"35260":39558,"35261":39608,"35262":39612,"35263":40077,"35264":40501,"35265":40490,"35266":40495,"35267":40493,"35268":40499,"35269":40857,"35270":40863,"35271":20248,"35272":20607,"35273":20648,"35274":21169,"35275":21659,"35276":21523,"35277":21387,"35278":22489,"35279":23156,"35280":23252,"35281":23351,"35282":23604,"35283":23654,"35284":23679,"35285":23896,"35286":24110,"35287":24357,"35288":24212,"35289":24691,"35290":25103,"35291":20987,"35292":25380,"35293":25319,"35294":25311,"35295":25601,"35296":25947,"35297":27609,"35298":26279,"35299":26723,"35300":26816,"35301":26727,"35302":26633,"35303":27183,"35304":27539,"35305":27617,"35306":27870,"35307":28392,"35308":27982,"35309":28059,"35310":28389,"35311":28073,"35312":28493,"35313":33829,"35314":28799,"35315":28891,"35316":28905,"35317":22681,"35318":29406,"35319":33719,"35320":29615,"35321":29815,"35322":30184,"35323":30103,"35324":30699,"35325":30970,"35326":30710,"35392":31699,"35393":31914,"35394":38214,"35395":31937,"35396":32553,"35397":32489,"35398":32554,"35399":32533,"35400":32551,"35401":32503,"35402":32541,"35403":24635,"35404":32437,"35405":32555,"35406":32420,"35407":32549,"35408":32358,"35409":32550,"35410":22768,"35411":32874,"35412":32852,"35413":32824,"35414":33043,"35415":32966,"35416":33080,"35417":33037,"35418":20020,"35419":20030,"35420":33392,"35421":34103,"35422":34015,"35423":20111,"35424":34684,"35425":34632,"35426":20149,"35427":35099,"35428":35274,"35429":35868,"35430":35876,"35431":35878,"35432":35762,"35433":35854,"35434":35875,"35435":35874,"35436":35466,"35437":35879,"35438":36186,"35439":36187,"35440":36141,"35441":36185,"35442":36235,"35443":36758,"35444":36759,"35445":27586,"35446":36757,"35447":33286,"35448":36824,"35449":36808,"35450":37213,"35451":38208,"35452":38209,"35453":38170,"35454":38190,"35489":38194,"35490":38149,"35491":38180,"35492":38202,"35493":38201,"35494":38203,"35495":38206,"35496":38199,"35497":38420,"35498":38421,"35499":38417,"35500":38385,"35501":38544,"35502":38582,"35503":34429,"35504":38889,"35505":39063,"35506":39123,"35507":39563,"35508":39567,"35509":40092,"35510":40091,"35511":40084,"35512":40081,"35513":40511,"35514":40509,"35515":28857,"35516":25995,"35517":19995,"35518":22108,"35519":22329,"35520":22418,"35521":23158,"35522":25041,"35523":25193,"35524":25527,"35525":25200,"35526":25781,"35527":25670,"35528":25822,"35529":25783,"35530":26029,"35531":27103,"35532":26588,"35533":27099,"35534":26592,"35535":27428,"35536":24402,"35537":27553,"35538":27899,"35539":28182,"35540":28388,"35541":28174,"35542":28293,"35543":27983,"35544":28908,"35545":28952,"35546":29367,"35547":29454,"35548":29934,"35549":30112,"35550":30545,"35551":30784,"35552":31036,"35553":31313,"35554":31229,"35555":31388,"35556":31373,"35557":31659,"35558":31783,"35559":31658,"35560":31697,"35561":31616,"35562":31918,"35563":32455,"35564":32558,"35565":32469,"35566":32557,"35567":32483,"35568":32559,"35569":32728,"35570":32844,"35571":32834,"35572":33040,"35573":33169,"35574":26087,"35575":33832,"35576":34013,"35577":33632,"35578":34546,"35579":34633,"35580":35280,"35581":35294,"35582":35871,"35648":35880,"35649":35884,"35650":35882,"35651":36184,"35652":36434,"35653":36857,"35654":36344,"35655":36527,"35656":36716,"35657":36761,"35658":36841,"35659":21307,"35660":37233,"35661":38225,"35662":38145,"35663":38056,"35664":38221,"35665":38215,"35666":38224,"35667":38226,"35668":38217,"35669":38422,"35670":38383,"35671":38423,"35672":38425,"35673":26434,"35674":21452,"35675":38607,"35676":40481,"35677":39069,"35678":39068,"35679":39064,"35680":39066,"35681":39067,"35682":39311,"35683":39306,"35684":39304,"35685":39569,"35686":39617,"35687":40104,"35688":40100,"35689":40107,"35690":40103,"35691":40515,"35692":40517,"35693":40516,"35694":22404,"35695":22364,"35696":23456,"35697":24222,"35698":24208,"35699":24809,"35700":24576,"35701":25042,"35702":25314,"35703":26103,"35704":27249,"35705":26911,"35706":27016,"35707":27257,"35708":28487,"35709":28625,"35710":27813,"35745":28626,"35746":27896,"35747":28865,"35748":29261,"35749":29322,"35750":20861,"35751":29549,"35752":29626,"35753":29756,"35754":30068,"35755":30250,"35756":30861,"35757":31095,"35758":31283,"35759":31614,"35760":33575,"35761":32462,"35762":32499,"35763":32472,"35764":32599,"35765":32564,"35766":33211,"35767":33402,"35768":34222,"35769":33647,"35770":34433,"35771":34631,"35772":35014,"35773":34948,"35774":35889,"35775":35782,"35776":35885,"35777":35890,"35778":35749,"35779":35887,"35780":36192,"35781":36190,"35782":36343,"35783":36762,"35784":36735,"35785":36766,"35786":36793,"35787":38236,"35788":38237,"35789":38238,"35790":38142,"35791":38231,"35792":38232,"35793":38230,"35794":38233,"35795":38197,"35796":38210,"35797":38143,"35798":37694,"35799":20851,"35800":38471,"35801":38590,"35802":38654,"35803":38892,"35804":38901,"35805":31867,"35806":39072,"35807":39125,"35808":39314,"35809":39313,"35810":39579,"35811":39575,"35812":40120,"35813":40115,"35814":40109,"35815":40119,"35816":40529,"35817":40521,"35818":40522,"35819":40524,"35820":40527,"35821":20029,"35822":40628,"35823":21149,"35824":21657,"35825":22052,"35826":20005,"35827":23453,"35828":24748,"35829":24527,"35830":25318,"35831":25600,"35832":32999,"35833":27015,"35834":28572,"35835":28491,"35836":28809,"35837":29649,"35838":30719,"35904":30778,"35905":30718,"35906":30782,"35907":31398,"35908":31454,"35909":31609,"35910":31726,"35911":36779,"35912":32548,"35913":32487,"35914":32578,"35915":33002,"35916":33328,"35917":34108,"35918":34106,"35919":33446,"35920":33529,"35921":34164,"35922":34461,"35923":35124,"35924":35273,"35925":35302,"35926":35758,"35927":35793,"35928":35893,"35929":36194,"35930":36193,"35931":36280,"35932":37322,"35933":38047,"35934":38105,"35935":38152,"35936":38416,"35937":39128,"35938":39286,"35939":39269,"35940":39582,"35941":33150,"35942":39578,"35943":40131,"35944":40133,"35945":20826,"35946":40835,"35947":40836,"35948":20458,"35949":21995,"35950":21869,"35951":22179,"35952":23646,"35953":24807,"35954":24913,"35955":25668,"35956":25658,"35957":26003,"35958":27185,"35959":26639,"35960":26818,"35961":27516,"35962":28866,"35963":29306,"35964":38262,"35965":29838,"35966":30302,"36001":32544,"36002":32493,"36003":20848,"36004":34259,"36005":34510,"36006":35272,"36007":35892,"36008":25252,"36009":35465,"36010":36163,"36011":36364,"36012":36291,"36013":36347,"36014":36720,"36015":36777,"36016":38256,"36017":38253,"36018":38081,"36019":38107,"36020":38094,"36021":38255,"36022":38220,"36023":21709,"36024":39038,"36025":39074,"36026":39144,"36027":39537,"36028":39584,"36029":34022,"36030":39585,"36031":39621,"36032":40141,"36033":40143,"36034":33722,"36035":40548,"36036":40542,"36037":40839,"36038":40840,"36039":21870,"36040":20456,"36041":20645,"36042":21587,"36043":23402,"36044":24005,"36045":23782,"36046":24367,"36047":25674,"36048":26435,"36049":27426,"36050":28393,"36051":29473,"36052":21472,"36053":30270,"36054":30307,"36055":31548,"36056":31809,"36057":32843,"36058":33039,"36059":34989,"36060":34924,"36061":35835,"36062":36174,"36063":36189,"36064":36399,"36065":36396,"36066":36756,"36067":37094,"36068":38136,"36069":37492,"36070":38657,"36071":38801,"36072":32366,"36073":39076,"36074":39556,"36075":39553,"36076":40150,"36077":40098,"36078":40148,"36079":40151,"36080":40551,"36081":40485,"36082":40761,"36083":40841,"36084":40842,"36085":40858,"36086":24651,"36087":25371,"36088":25605,"36089":29906,"36090":31363,"36091":32552,"36092":33250,"36093":33821,"36094":34506,"36160":21464,"36161":36902,"36162":36923,"36163":38259,"36164":38084,"36165":38757,"36166":26174,"36167":39181,"36168":24778,"36169":39551,"36170":39564,"36171":39635,"36172":39633,"36173":40157,"36174":40158,"36175":40156,"36176":40502,"36177":22065,"36178":22365,"36179":25597,"36180":30251,"36181":30315,"36182":32641,"36183":34453,"36184":35753,"36185":35863,"36186":35894,"36187":33395,"36188":36195,"36189":37247,"36190":38643,"36191":28789,"36192":38701,"36193":39078,"36194":39588,"36195":39699,"36196":39751,"36197":40078,"36198":40560,"36199":40557,"36200":30839,"36201":30416,"36202":40140,"36203":40844,"36204":40843,"36205":21381,"36206":27012,"36207":28286,"36208":31729,"36209":31657,"36210":34542,"36211":35266,"36212":36433,"36213":34885,"36214":38053,"36215":39045,"36216":39307,"36217":39627,"36218":40649,"36219":28390,"36220":30633,"36221":38218,"36222":38831,"36257":39540,"36258":39589,"36259":32518,"36260":35872,"36261":36495,"36262":37245,"36263":38075,"36264":37550,"36265":38179,"36266":40132,"36267":40072,"36268":40681,"36269":20991,"36270":40550,"36271":39562,"36272":40563,"36273":40510,"36274":38074,"36275":20162,"36276":34381,"36277":27538,"36278":22439,"36279":22395,"36280":25099,"36281":20451,"36282":21037,"36283":21389,"36284":21593,"36285":21370,"36286":32424,"36287":33543,"36288":38023,"36289":38022,"36290":21591,"36291":24362,"36292":31059,"36293":32446,"36294":37071,"36295":38028,"36296":21072,"36297":21286,"36298":22261,"36299":22445,"36300":23045,"36301":23741,"36302":23811,"36303":28062,"36304":28172,"36305":28867,"36306":30502,"36307":32448,"36308":32464,"36309":33003,"36310":38030,"36311":38032,"36312":38037,"36313":38029,"36314":38379,"36315":22955,"36316":23899,"36317":24701,"36318":26720,"36319":26536,"36320":27817,"36321":27976,"36322":30066,"36323":30743,"36324":32471,"36325":33757,"36326":35271,"36327":35765,"36328":35790,"36329":35794,"36330":36150,"36331":36147,"36332":36730,"36333":36725,"36334":36728,"36335":36911,"36336":37075,"36337":37124,"36338":38059,"36339":38060,"36340":38043,"36341":38063,"36342":38061,"36343":38058,"36344":38390,"36345":38503,"36346":39032,"36347":39275,"36348":40697,"36349":20251,"36350":20603,"36416":20325,"36417":21794,"36418":22450,"36419":24047,"36420":24493,"36421":28828,"36422":33557,"36423":29426,"36424":29614,"36425":32488,"36426":32480,"36427":32481,"36428":32671,"36429":33645,"36430":34545,"36431":35795,"36432":35798,"36433":35817,"36434":35796,"36435":35804,"36436":36241,"36437":36738,"36438":36737,"36439":37036,"36440":38090,"36441":38088,"36442":38064,"36443":38066,"36444":38070,"36445":38157,"36446":38092,"36447":38077,"36448":38076,"36449":39043,"36450":39040,"36451":20971,"36452":40702,"36453":20606,"36454":21787,"36455":23901,"36456":24123,"36457":24747,"36458":24749,"36459":24580,"36460":25132,"36461":25111,"36462":25247,"36463":25248,"36464":25532,"36465":26724,"36466":26473,"36467":33637,"36468":27986,"36469":27812,"36470":28829,"36471":30386,"36472":30720,"36473":32507,"36474":32498,"36475":32495,"36476":32506,"36477":33715,"36478":35275,"36513":35830,"36514":36167,"36515":38129,"36516":38098,"36517":38097,"36518":38101,"36519":38111,"36520":38123,"36521":38127,"36522":38122,"36523":38135,"36524":38102,"36525":38117,"36526":39121,"36527":21055,"36528":21154,"36529":21715,"36530":21586,"36531":23810,"36532":23780,"36533":24209,"36534":24870,"36535":25378,"36536":26912,"36537":27637,"36538":39053,"36539":28061,"36540":28514,"36541":28064,"36542":28375,"36543":29711,"36544":29825,"36545":30231,"36546":32515,"36547":32535,"36548":32524,"36549":32527,"36550":32529,"36551":33628,"36552":33932,"36553":33553,"36554":33473,"36555":35833,"36556":35836,"36557":35842,"36558":36181,"36559":37112,"36560":38162,"36561":38103,"36562":38141,"36563":38163,"36564":38154,"36565":38116,"36566":38150,"36567":38151,"36568":38164,"36569":38406,"36570":38403,"36571":38739,"36572":39055,"36573":39293,"36574":39541,"36575":39552,"36576":40066,"36577":40488,"36578":21714,"36579":21717,"36580":21721,"36581":23250,"36582":23748,"36583":24639,"36584":27546,"36585":27981,"36586":28904,"36587":29443,"36588":29423,"36589":30876,"36590":31405,"36591":32279,"36592":32539,"36593":33927,"36594":33640,"36595":33929,"36596":33630,"36597":33720,"36598":33431,"36599":34547,"36600":35816,"36601":35857,"36602":35860,"36603":35869,"36604":37072,"36605":38185,"36606":38188,"36672":38166,"36673":38167,"36674":38140,"36675":38171,"36676":38165,"36677":38174,"36678":38036,"36679":38415,"36680":38408,"36681":38409,"36682":38410,"36683":38412,"36684":38413,"36685":40498,"36686":40497,"36687":21724,"36688":24113,"36689":24697,"36690":25672,"36691":58305,"36692":27894,"36693":29461,"36694":29971,"36695":30213,"36696":30187,"36697":30807,"36698":31654,"36699":31578,"36700":31976,"36701":32545,"36702":32807,"36703":33631,"36704":33718,"36705":34544,"36706":35042,"36707":35279,"36708":35873,"36709":35788,"36710":35877,"36711":36292,"36712":38200,"36713":38196,"36714":38113,"36715":38198,"36716":38418,"36717":39271,"36718":40082,"36719":40085,"36720":40504,"36721":40505,"36722":40506,"36723":40832,"36724":24636,"36725":25669,"36726":25784,"36727":27898,"36728":30102,"36729":32523,"36730":32873,"36731":33641,"36732":34789,"36733":34414,"36734":35764,"36769":35881,"36770":36188,"36771":36157,"36772":36760,"36773":37021,"36774":38227,"36775":38112,"36776":38204,"36777":38223,"36778":34021,"36779":38890,"36780":39273,"36781":39568,"36782":39570,"36783":39571,"36784":38411,"36785":40105,"36786":40096,"36787":40520,"36788":40513,"36789":40518,"36790":21411,"36791":21590,"36792":22406,"36793":27104,"36794":26638,"36795":27655,"36796":27895,"36797":28486,"36798":31074,"36799":32562,"36800":32563,"36801":32628,"36802":33315,"36803":34511,"36804":34431,"36805":35043,"36806":35281,"36807":35311,"36808":35886,"36809":38235,"36810":38239,"36811":38250,"36812":38214,"36813":38121,"36814":38891,"36815":39073,"36816":39312,"36817":39618,"36818":40117,"36819":40118,"36820":40123,"36821":40113,"36822":40526,"36823":40491,"36824":40700,"36825":21950,"36826":25732,"36827":26634,"36828":26533,"36829":26636,"36830":32561,"36831":32845,"36832":33551,"36833":33480,"36834":34162,"36835":34548,"36836":34686,"36837":38132,"36838":38246,"36839":38248,"36840":38241,"36841":38243,"36842":38212,"36843":38251,"36844":38119,"36845":38244,"36846":38137,"36847":38426,"36848":39071,"36849":39316,"36850":39546,"36851":39581,"36852":39583,"36853":39576,"36854":40535,"36855":40538,"36856":40540,"36857":40838,"36858":40837,"36859":20649,"36860":23743,"36861":30152,"36862":25786,"36928":27017,"36929":28384,"36930":30779,"36931":31901,"36932":32425,"36933":32556,"36934":34105,"36935":36166,"36936":38257,"36937":38396,"36938":39129,"36939":39586,"36940":39574,"36941":39580,"36942":40101,"36943":40142,"36944":40144,"36945":40547,"36946":40536,"36947":40574,"36948":20865,"36949":23048,"36950":28757,"36951":25874,"36952":30271,"36953":31656,"36954":31860,"36955":33339,"36956":35276,"36957":36345,"36958":36318,"36959":36729,"36960":38228,"36961":38252,"36962":39587,"36963":39557,"36964":40149,"36965":40099,"36966":40102,"36967":40552,"36968":40503,"36969":40859,"36970":26686,"36971":26916,"36972":34016,"36973":38624,"36974":36723,"36975":40159,"36976":40095,"36977":40553,"36978":40556,"36979":40554,"36980":40555,"36981":40519,"36982":28751,"36983":31766,"36984":35888,"36985":39628,"36986":31550,"36987":31900,"36988":32565,"36989":33044,"36990":36479,"37025":38247,"37026":40090,"37027":36273,"37028":36508,"37029":37246,"37030":35891,"37031":39070,"37032":39079,"37033":39591,"37034":40492,"37035":25094,"37036":38404,"37037":40097,"37038":40514,"37039":31160,"37040":25300,"37041":36299,"37042":29648,"37043":23467,"37044":25296,"37045":27585,"37046":20943,"37047":31108,"37048":21525,"37049":28508,"37050":34972,"37051":37095,"37052":20857,"37053":25144,"37054":25243,"37055":25383,"37056":25531,"37057":25566,"37058":25594,"37059":25745,"37060":25792,"37061":25825,"37062":25846,"37063":25861,"37064":25909,"37065":25934,"37066":25963,"37067":25992,"37068":26073,"37069":26142,"37070":26171,"37071":26175,"37072":26180,"37073":26199,"37074":26217,"37075":26227,"37076":26243,"37077":26300,"37078":26303,"37079":26305,"37080":26357,"37081":26362,"37082":26363,"37083":26382,"37084":26390,"37085":26423,"37086":26468,"37087":26470,"37088":26534,"37089":26535,"37090":26537,"37091":26619,"37092":26621,"37093":26624,"37094":26625,"37095":26629,"37096":26654,"37097":26698,"37098":26706,"37099":26709,"37100":26713,"37101":26765,"37102":26809,"37103":26831,"37104":20616,"37105":38184,"37106":40087,"37107":26914,"37108":26918,"37109":220,"37110":58591,"37111":58592,"37112":252,"37113":58594,"37114":58595,"37115":220,"37116":252,"37117":26934,"37118":26977,"37184":33477,"37185":33482,"37186":33496,"37187":33560,"37188":33562,"37189":33571,"37190":33606,"37191":33627,"37192":33634,"37193":33644,"37194":33646,"37195":33692,"37196":33695,"37197":33717,"37198":33724,"37199":33783,"37200":33834,"37201":33864,"37202":33884,"37203":33890,"37204":33924,"37205":33928,"37206":34012,"37207":34019,"37208":34104,"37209":34138,"37210":34199,"37211":34219,"37212":34241,"37213":34323,"37214":34326,"37215":8715,"37216":34581,"37217":34672,"37218":34685,"37219":34699,"37220":34728,"37221":34759,"37222":34768,"37223":34823,"37224":34830,"37225":34855,"37226":34990,"37227":8712,"37228":34997,"37229":35007,"37230":35045,"37231":35061,"37232":35100,"37233":35101,"37234":35191,"37235":35303,"37236":35383,"37237":35500,"37238":35546,"37239":35675,"37240":35697,"37241":35883,"37242":35898,"37243":35964,"37244":35982,"37245":36014,"37246":36114,"37281":36169,"37282":36173,"37283":36209,"37284":36360,"37285":36410,"37286":36464,"37287":36505,"37288":36528,"37289":36529,"37290":36549,"37291":36550,"37292":36558,"37293":36579,"37294":36620,"37295":36721,"37296":36727,"37297":36775,"37298":36847,"37299":36878,"37300":36921,"37301":36965,"37302":37001,"37303":37086,"37304":37141,"37305":37334,"37306":37339,"37307":37342,"37308":37345,"37309":37349,"37310":37366,"37311":37372,"37312":37417,"37313":37420,"37314":65287,"37315":37465,"37316":37495,"37317":37613,"37318":37690,"37319":58701,"37320":58702,"37321":29227,"37322":20866,"37323":20886,"37324":20023,"37325":20843,"37326":20799,"37327":58709,"37328":58710,"37329":26409,"37330":27706,"37331":21378,"37332":30098,"37333":32896,"37334":34916,"37335":19974,"37336":58718,"37337":58719,"37338":58720,"37339":11927,"37340":21241,"37341":21269,"37342":8225,"37343":58725,"37344":13316,"37345":58727,"37346":58728,"37347":58729,"37348":58730,"37349":58731,"37350":20981,"37351":58733,"37352":23662,"37353":58735,"37354":22231,"37355":20128,"37356":20907,"37357":11904,"37358":27079,"37359":58741,"37360":9550,"37361":9688,"37362":9689,"37363":9794,"37364":9654,"37365":9668,"37366":8597,"37367":8252,"37368":182,"37369":8704,"37370":8616,"37371":8596,"37372":8962,"37373":58755,"37374":58756,"37440":20124,"37441":24746,"37442":22311,"37443":22258,"37444":21307,"37445":22769,"37446":36920,"37447":38560,"37448":26628,"37449":21942,"37450":39365,"37451":35585,"37452":20870,"37453":32257,"37454":24540,"37455":27431,"37456":27572,"37457":26716,"37458":22885,"37459":31311,"37460":20206,"37461":20385,"37462":30011,"37463":28784,"37464":20250,"37465":24724,"37466":28023,"37467":32117,"37468":22730,"37469":25040,"37470":25313,"37471":27579,"37472":35226,"37473":23398,"37474":27005,"37475":21917,"37476":28167,"37477":58794,"37478":24059,"37479":38501,"37480":21223,"37481":23515,"37482":28450,"37483":38306,"37484":27475,"37485":35251,"37486":27671,"37487":24112,"37488":25135,"37489":29344,"37490":34384,"37491":26087,"37492":24613,"37493":25312,"37494":25369,"37495":34394,"37496":23777,"37497":25375,"37498":29421,"37499":37111,"37500":38911,"37501":26241,"37502":21220,"37537":35641,"37538":21306,"37539":39366,"37540":21234,"37541":58824,"37542":24452,"37543":33550,"37544":24693,"37545":25522,"37546":28179,"37547":32076,"37548":34509,"37549":36605,"37550":32153,"37551":40335,"37552":25731,"37553":30476,"37554":20537,"37555":21091,"37556":38522,"37557":22287,"37558":26908,"37559":27177,"37560":38997,"37561":39443,"37562":21427,"37563":21577,"37564":23087,"37565":35492,"37566":24195,"37567":28207,"37568":37489,"37569":21495,"37570":22269,"37571":40658,"37572":31296,"37573":30741,"37574":28168,"37575":25998,"37576":27507,"37577":21092,"37578":38609,"37579":21442,"37580":26719,"37581":24808,"37582":36059,"37583":27531,"37584":27503,"37585":20816,"37586":36766,"37587":28287,"37588":23455,"37589":20889,"37590":33294,"37591":25448,"37592":37320,"37593":23551,"37594":21454,"37595":34886,"37596":24467,"37597":28171,"37598":29539,"37599":32294,"37600":31899,"37601":20966,"37602":23558,"37603":31216,"37604":28169,"37605":28988,"37606":22888,"37607":26465,"37608":29366,"37609":20055,"37610":27972,"37611":21104,"37612":30067,"37613":32260,"37614":22732,"37615":23330,"37616":35698,"37617":37304,"37618":35302,"37619":22065,"37620":23517,"37621":23613,"37622":22259,"37623":31883,"37624":37204,"37625":31298,"37626":38543,"37627":39620,"37628":26530,"37629":25968,"37630":25454,"37696":28716,"37697":22768,"37698":25993,"37699":38745,"37700":31363,"37701":25666,"37702":32118,"37703":23554,"37704":27973,"37705":25126,"37706":36341,"37707":37549,"37708":28508,"37709":36983,"37710":36984,"37711":32330,"37712":31109,"37713":30094,"37714":22766,"37715":20105,"37716":33624,"37717":25436,"37718":25407,"37719":24035,"37720":31379,"37721":35013,"37722":20711,"37723":23652,"37724":32207,"37725":39442,"37726":22679,"37727":24974,"37728":34101,"37729":36104,"37730":33235,"37731":23646,"37732":32154,"37733":22549,"37734":23550,"37735":24111,"37736":28382,"37737":28381,"37738":25246,"37739":27810,"37740":28655,"37741":21336,"37742":22022,"37743":22243,"37744":26029,"37745":24382,"37746":36933,"37747":26172,"37748":37619,"37749":24193,"37750":24500,"37751":32884,"37752":25074,"37753":22618,"37754":36883,"37755":37444,"37756":28857,"37757":36578,"37758":20253,"37793":38651,"37794":28783,"37795":24403,"37796":20826,"37797":30423,"37798":31282,"37799":38360,"37800":24499,"37801":27602,"37802":29420,"37803":35501,"37804":23626,"37805":38627,"37806":24336,"37807":24745,"37808":33075,"37809":25309,"37810":24259,"37811":22770,"37812":26757,"37813":21338,"37814":34180,"37815":40614,"37816":32283,"37817":30330,"37818":39658,"37819":25244,"37820":27996,"37821":27996,"37822":25935,"37823":25975,"37824":20398,"37825":25173,"37826":20175,"37827":36794,"37828":22793,"37829":27497,"37830":33303,"37831":31807,"37832":21253,"37833":23453,"37834":25265,"37835":27873,"37836":32990,"37837":30770,"37838":35914,"37839":39165,"37840":22696,"37841":27598,"37842":28288,"37843":33032,"37844":40665,"37845":35379,"37846":34220,"37847":36493,"37848":19982,"37849":35465,"37850":25671,"37851":27096,"37852":35617,"37853":26332,"37854":26469,"37855":38972,"37856":20081,"37857":35239,"37858":31452,"37859":38534,"37860":26053,"37861":20001,"37862":29471,"37863":32209,"37864":28057,"37865":22593,"37866":31036,"37867":21169,"37868":25147,"37869":38666,"37870":40802,"37871":26278,"37872":27508,"37873":24651,"37874":32244,"37875":37676,"37876":28809,"37877":21172,"37878":27004,"37879":37682,"37880":28286,"37881":24357,"37882":20096,"37883":26365,"37884":22985,"37885":23437,"37886":23947,"37952":27179,"37953":26907,"37954":21936,"37955":31874,"37956":36796,"37957":27018,"37958":21682,"37959":40235,"37960":38635,"37961":26905,"37962":25539,"37963":39364,"37964":20967,"37965":26626,"37966":36795,"37967":20685,"37968":23776,"37969":26627,"37970":20970,"37971":21250,"37972":30834,"37973":30033,"37974":30048,"37975":22138,"37976":37618,"37977":22592,"37978":26622,"37979":20451,"37980":26466,"37981":31870,"37982":21249,"37983":20452,"37984":20453,"37985":20969,"37986":21498,"37987":21720,"37988":22222,"37989":22310,"37990":22327,"37991":22328,"37992":22408,"37993":22451,"37994":22442,"37995":22448,"37996":22486,"37997":22640,"37998":22713,"37999":22743,"38000":23670,"38001":23740,"38002":23749,"38003":23742,"38004":23926,"38005":24342,"38006":24634,"38007":25525,"38008":26433,"38009":26467,"38010":26529,"38011":26810,"38012":26917,"38013":26920,"38014":27258,"38049":26915,"38050":26913,"38051":27006,"38052":27009,"38053":27101,"38054":27182,"38055":27250,"38056":27423,"38057":27615,"38058":28181,"38059":29077,"38060":29927,"38061":29938,"38062":29936,"38063":29937,"38064":29944,"38065":29957,"38066":30057,"38067":30314,"38068":30836,"38069":31437,"38070":31439,"38071":31445,"38072":31443,"38073":31457,"38074":31472,"38075":31490,"38076":31763,"38077":31767,"38078":31888,"38079":31917,"38080":31936,"38081":31960,"38082":32155,"38083":32261,"38084":32359,"38085":32387,"38086":32400,"38087":33188,"38088":33373,"38089":33826,"38090":34009,"38091":34352,"38092":34475,"38093":34543,"38094":34992,"38095":35011,"38096":35012,"38097":35076,"38098":59183,"38099":36542,"38100":36552,"38101":36684,"38102":36791,"38103":36826,"38104":36903,"38105":36950,"38106":37685,"38107":37691,"38108":37817,"38109":38282,"38110":38294,"38111":38777,"38112":38790,"38113":38800,"38114":39082,"38115":39830,"38116":39831,"38117":39860,"38118":39887,"38119":39889,"38120":39890,"38121":39922,"38122":39921,"38123":39984,"38124":40007,"38125":40026,"38126":40176,"38127":40262,"38128":40292,"38129":40363,"38130":20036,"38131":21583,"38132":25368,"38133":39857,"38134":40041,"38135":40263,"38136":40293,"38137":39983,"38138":40639,"38139":20916,"38140":21610,"38141":26528,"38142":39822,"38208":37032,"38209":20914,"38210":13869,"38211":25285,"38212":21189,"38213":26545,"38214":21709,"38215":24658,"38216":21441,"38217":28913,"38218":22531,"38219":21855,"38220":37390,"38221":30528,"38222":29756,"38223":29002,"38224":28377,"38225":21472,"38226":29486,"38227":35023,"38228":30861,"38229":32675,"38230":32171,"38231":36394,"38232":37979,"38233":25452,"38234":24487,"38235":23557,"38236":32827,"38237":23791,"38238":14776,"38239":29009,"38240":36045,"38241":38894,"38242":22642,"38243":23139,"38244":32632,"38245":23895,"38246":24943,"38247":27032,"38248":32137,"38249":31918,"38250":32179,"38251":28545,"38252":23290,"38253":22715,"38254":29269,"38255":30286,"38256":36653,"38257":37561,"38258":40286,"38259":40623,"38260":32583,"38261":40388,"38262":36120,"38263":20915,"38264":34412,"38265":21668,"38266":21414,"38267":21030,"38268":26422,"38269":20001,"38270":21364,"38305":24313,"38306":21177,"38307":21647,"38308":24312,"38309":22956,"38310":24625,"38311":29248,"38312":33047,"38313":30267,"38314":24333,"38315":26187,"38316":26280,"38317":24932,"38318":25423,"38319":28895,"38320":27940,"38321":31911,"38322":31945,"38323":21465,"38324":25933,"38325":22338,"38326":29647,"38327":32966,"38328":13649,"38329":27445,"38330":30849,"38331":21452,"38332":29483,"38333":29482,"38334":29641,"38335":30026,"38336":23033,"38337":29124,"38338":29966,"38339":32220,"38340":39393,"38341":35241,"38342":28662,"38343":14935,"38344":25834,"38345":15341,"38346":27809,"38347":28284,"38348":30055,"38349":22633,"38350":22633,"38351":20996,"38352":59338,"38353":24967,"38354":25658,"38355":33263,"38356":59342,"38357":20917,"38358":20945,"38359":27769,"38360":22815,"38361":36857,"38362":39153,"38363":25911,"38364":33033,"38365":34996,"38366":14890,"38367":36525,"38368":32663,"38369":39440,"38370":32037,"38371":27336,"38372":20876,"38373":21031,"38374":59360,"38375":33050,"38376":21408,"38377":21410,"38378":27738,"38379":27703,"38380":33304,"38381":21894,"38382":24315,"38383":20937,"38384":30897,"38385":37474,"38386":21357,"38387":20931,"38388":59374,"38389":33905,"38390":35207,"38391":38765,"38392":35728,"38393":38563,"38394":24316,"38395":38583,"38396":20814,"38397":39952,"38398":26160,"38464":37461,"38465":30728,"38466":37701,"38467":37491,"38468":37737,"38469":59390,"38470":59391,"38471":59392,"38472":59393,"38473":37343,"38474":37338,"38475":30804,"38476":30822,"38477":30856,"38478":30902,"38479":30919,"38480":30930,"38481":30935,"38482":8491,"38483":8651,"38484":30948,"38485":30958,"38486":30960,"38487":30961,"38488":30965,"38489":31026,"38490":31027,"38491":31030,"38492":31064,"38493":12307,"38494":31065,"38495":31089,"38496":31102,"38497":31107,"38498":31110,"38499":31111,"38500":31121,"38501":31129,"38502":31135,"38503":31141,"38504":31202,"38505":31217,"38506":31220,"38507":31274,"38508":31290,"38509":31301,"38510":31333,"38511":31420,"38512":31426,"38513":31433,"38514":31451,"38515":31465,"38516":31486,"38517":31500,"38518":31527,"38519":31529,"38520":31554,"38521":31555,"38522":31573,"38523":31599,"38524":31666,"38525":27102,"38526":27129,"38561":37238,"38562":33114,"38563":33527,"38564":21579,"38565":33074,"38566":32957,"38567":33816,"38568":37214,"38569":37232,"38570":37260,"38571":33096,"38572":59459,"38573":17462,"38574":33113,"38575":32927,"38576":59463,"38577":21833,"38578":21537,"38579":21722,"38580":21554,"38581":21945,"38582":21652,"38583":59470,"38584":30802,"38585":30789,"38586":30796,"38587":59474,"38588":33981,"38589":33820,"38590":33476,"38591":59478,"38592":33915,"38593":35629,"38594":59481,"38595":22347,"38596":59483,"38597":59484,"38598":22341,"38599":34766,"38600":22112,"38601":21994,"38602":22139,"38603":32956,"38604":59491,"38605":30904,"38606":27148,"38607":21708,"38608":31696,"38609":31724,"38610":31738,"38611":31765,"38612":31771,"38613":31797,"38614":31812,"38615":31853,"38616":31886,"38617":31928,"38618":31939,"38619":31974,"38620":31981,"38621":31987,"38622":31989,"38623":31993,"38624":59511,"38625":31996,"38626":32139,"38627":32151,"38628":32164,"38629":32168,"38630":32205,"38631":32208,"38632":32211,"38633":32229,"38634":32253,"38635":27154,"38636":27170,"38637":27184,"38638":27190,"38639":27237,"38640":59527,"38641":59528,"38642":59529,"38643":59530,"38644":59531,"38645":59532,"38646":59533,"38647":59534,"38648":27251,"38649":27256,"38650":59537,"38651":59538,"38652":27260,"38653":27305,"38654":27306,"38720":9450,"38721":9312,"38722":9313,"38723":9314,"38724":9315,"38725":9316,"38726":9317,"38727":9318,"38728":9319,"38729":9320,"38730":9321,"38731":9322,"38732":9323,"38733":9324,"38734":9325,"38735":9326,"38736":9327,"38737":9328,"38738":9329,"38739":9330,"38740":9331,"38741":37700,"38742":37805,"38743":37830,"38744":37861,"38745":37914,"38746":37921,"38747":37950,"38748":37953,"38749":37971,"38750":37978,"38751":38042,"38752":38071,"38753":38104,"38754":38110,"38755":38131,"38756":38147,"38757":38158,"38758":38159,"38759":38168,"38760":38173,"38761":38186,"38762":38187,"38763":38207,"38764":38213,"38765":38222,"38766":38242,"38767":38245,"38768":38249,"38769":38258,"38770":38279,"38771":38297,"38772":38304,"38773":38322,"38774":38502,"38775":38557,"38776":38575,"38777":38578,"38778":38707,"38779":38715,"38780":38733,"38781":38735,"38782":38737,"38817":38741,"38818":38756,"38819":38763,"38820":38769,"38821":38802,"38822":38834,"38823":38898,"38824":38973,"38825":38996,"38826":39077,"38827":39107,"38828":39130,"38829":39150,"38830":39197,"38831":39200,"38832":39267,"38833":39296,"38834":39303,"38835":39309,"38836":39315,"38837":39317,"38838":39356,"38839":39368,"38840":39410,"38841":39606,"38842":39641,"38843":39646,"38844":39695,"38845":39753,"38846":39794,"38847":39811,"38848":39839,"38849":39867,"38850":39907,"38851":39925,"38852":39936,"38853":39940,"38854":39963,"38855":9398,"38856":9399,"38857":9400,"38858":9401,"38859":9402,"38860":9403,"38861":9404,"38862":9405,"38863":9406,"38864":9407,"38865":9408,"38866":9409,"38867":9410,"38868":9411,"38869":9412,"38870":9413,"38871":9414,"38872":9415,"38873":9416,"38874":9417,"38875":9418,"38876":9419,"38877":9420,"38878":9421,"38879":9422,"38880":9423,"38881":9424,"38882":9425,"38883":9426,"38884":9427,"38885":9428,"38886":9429,"38887":9430,"38888":9431,"38889":9432,"38890":9433,"38891":9434,"38892":9435,"38893":9436,"38894":9437,"38895":9438,"38896":9439,"38897":9440,"38898":9441,"38899":9442,"38900":9443,"38901":9444,"38902":9445,"38903":9446,"38904":9447,"38905":9448,"38906":9449,"38907":174,"38908":8482,"38909":59697,"38910":59698,"38976":40054,"38977":10122,"38978":10123,"38979":10124,"38980":10125,"38981":10126,"38982":10127,"38983":10128,"38984":10129,"38985":10130,"38986":10131,"38987":40069,"38988":40070,"38989":40071,"38990":40075,"38991":40080,"38992":40094,"38993":40110,"38994":40112,"38995":40114,"38996":40116,"38997":40122,"38998":40124,"38999":40125,"39000":40134,"39001":40135,"39002":40138,"39003":40139,"39004":40147,"39005":40152,"39006":40153,"39007":40162,"39008":40171,"39009":40172,"39010":40234,"39011":40264,"39012":40272,"39013":40314,"39014":40390,"39015":40523,"39016":40533,"39017":40539,"39018":40561,"39019":40618,"39020":40637,"39021":40644,"39022":40674,"39023":40682,"39024":40712,"39025":40715,"39026":40717,"39027":40737,"39028":40772,"39029":40785,"39030":40861,"39031":64014,"39032":64015,"39033":64017,"39034":64019,"39035":64020,"39036":64024,"39037":64031,"39038":64032,"39073":64033,"39074":64035,"39075":64036,"39076":64039,"39077":64040,"39078":64041,"39079":19972,"39080":20015,"39081":20097,"39082":20103,"39083":20131,"39084":20151,"39085":20156,"39086":20216,"39087":20264,"39088":20265,"39089":20279,"39090":20290,"39091":20293,"39092":20299,"39093":20338,"39094":20386,"39095":20400,"39096":20413,"39097":20424,"39098":20428,"39099":20464,"39100":20466,"39101":20473,"39102":20483,"39103":20488,"39104":20532,"39105":20539,"39106":20568,"39107":20582,"39108":20609,"39109":20624,"39110":20668,"39111":20688,"39112":20703,"39113":20705,"39114":20732,"39115":20749,"39116":20779,"39117":20832,"39118":20910,"39119":20920,"39120":20946,"39121":20962,"39122":20997,"39123":21044,"39124":21052,"39125":21081,"39126":21096,"39127":21113,"39128":21156,"39129":21196,"39130":21287,"39131":21314,"39132":21341,"39133":21373,"39134":21374,"39135":21445,"39136":21456,"39137":21458,"39138":21502,"39139":21613,"39140":21637,"39141":21651,"39142":21662,"39143":21689,"39144":21731,"39145":21743,"39146":21773,"39147":21784,"39148":21797,"39149":21800,"39150":21803,"39151":21831,"39152":21881,"39153":21904,"39154":21940,"39155":21953,"39156":21975,"39157":21976,"39158":22011,"39159":20404,"39160":22049,"39161":8707,"39162":22098,"39163":59852,"39164":9787,"39165":59854,"39166":59855,"39232":22109,"39233":9332,"39234":9333,"39235":9334,"39236":9335,"39237":9336,"39238":9337,"39239":9338,"39240":9339,"39241":9340,"39242":9341,"39243":9342,"39244":9343,"39245":9344,"39246":9345,"39247":9346,"39248":9347,"39249":9348,"39250":9349,"39251":9350,"39252":9351,"39253":22113,"39254":22153,"39255":22155,"39256":22174,"39257":22177,"39258":22193,"39259":22201,"39260":22207,"39261":22230,"39262":22255,"39263":22293,"39264":22301,"39265":22322,"39266":22333,"39267":22335,"39268":22339,"39269":8660,"39270":22398,"39271":22410,"39272":22413,"39273":22416,"39274":22428,"39275":22459,"39276":22462,"39277":22468,"39278":22494,"39279":22526,"39280":22546,"39281":22562,"39282":22599,"39283":22620,"39284":22623,"39285":22643,"39286":22695,"39287":22698,"39288":22704,"39289":22709,"39290":22710,"39291":22731,"39292":22736,"39293":22752,"39294":22789,"39329":22801,"39330":22921,"39331":22932,"39332":22938,"39333":22943,"39334":22960,"39335":22968,"39336":22980,"39337":23023,"39338":23024,"39339":23032,"39340":23042,"39341":23051,"39342":23053,"39343":23058,"39344":23073,"39345":23076,"39346":23079,"39347":23082,"39348":23083,"39349":23084,"39350":23101,"39351":23109,"39352":23124,"39353":23129,"39354":23137,"39355":23144,"39356":23147,"39357":23150,"39358":23153,"39359":23161,"39360":23166,"39361":23169,"39362":23170,"39363":23174,"39364":23176,"39365":23185,"39366":23193,"39367":23200,"39368":23201,"39369":23211,"39370":23235,"39371":23246,"39372":23247,"39373":23251,"39374":23268,"39375":23280,"39376":23294,"39377":23309,"39378":23313,"39379":23317,"39380":23327,"39381":23339,"39382":23361,"39383":23364,"39384":23366,"39385":23370,"39386":23375,"39387":23400,"39388":23412,"39389":23414,"39390":23420,"39391":23426,"39392":23440,"39393":9372,"39394":9373,"39395":9374,"39396":9375,"39397":9376,"39398":9377,"39399":9378,"39400":9379,"39401":9380,"39402":9381,"39403":9382,"39404":9383,"39405":9384,"39406":9385,"39407":9386,"39408":9387,"39409":9388,"39410":9389,"39411":9390,"39412":9391,"39413":9392,"39414":9393,"39415":9394,"39416":9395,"39417":9396,"39418":9397,"39419":60009,"39420":12850,"39421":12849,"39422":27307,"39488":23446,"39489":9352,"39490":9353,"39491":9354,"39492":9355,"39493":9356,"39494":9357,"39495":9358,"39496":9359,"39497":9360,"39498":9361,"39499":9362,"39500":9363,"39501":9364,"39502":9365,"39503":9366,"39504":9367,"39505":9368,"39506":9369,"39507":9370,"39508":9371,"39509":23509,"39510":23511,"39511":23587,"39512":23685,"39513":23710,"39514":23746,"39515":23824,"39516":23852,"39517":23855,"39518":23880,"39519":23894,"39520":23920,"39521":23931,"39522":23941,"39523":23972,"39524":23979,"39525":23990,"39526":24001,"39527":24023,"39528":24073,"39529":24136,"39530":24210,"39531":24253,"39532":24334,"39533":24434,"39534":24497,"39535":24514,"39536":24539,"39537":24543,"39538":24611,"39539":24702,"39540":24791,"39541":24839,"39542":24844,"39543":24857,"39544":24866,"39545":24912,"39546":24928,"39547":24961,"39548":24981,"39549":25017,"39550":25024,"39585":25039,"39586":25043,"39587":25050,"39588":25232,"39589":25393,"39590":8835,"39591":25399,"39592":25465,"39593":25483,"39594":25537,"39595":25570,"39596":25574,"39597":25595,"39598":25598,"39599":25607,"39600":25650,"39601":25656,"39602":25659,"39603":25690,"39604":25713,"39605":25724,"39606":25741,"39607":25775,"39608":25780,"39609":25782,"39610":25821,"39611":25829,"39612":25866,"39613":25873,"39614":25887,"39615":25951,"39616":25965,"39617":25990,"39618":26037,"39619":26046,"39620":26065,"39621":26068,"39622":26083,"39623":26111,"39624":26136,"39625":26147,"39626":26211,"39627":26219,"39628":26237,"39629":26245,"39630":26258,"39631":26266,"39632":26276,"39633":26285,"39634":26291,"39635":26294,"39636":26317,"39637":26318,"39638":26370,"39639":26380,"39640":26393,"39641":26436,"39642":26475,"39643":26511,"39644":26532,"39645":26559,"39646":26582,"39647":26583,"39648":8834,"39649":26637,"39650":26640,"39651":26651,"39652":26678,"39653":26695,"39654":26710,"39655":26756,"39656":26760,"39657":26813,"39658":26819,"39659":26821,"39660":26882,"39661":26883,"39662":26889,"39663":26904,"39664":26947,"39665":26950,"39666":26980,"39667":26983,"39668":26994,"39669":27013,"39670":27039,"39671":27042,"39672":27089,"39673":27093,"39674":27094,"39675":39457,"39676":39462,"39677":39471,"39678":27329,"39744":22975,"39745":27105,"39746":27139,"39747":27162,"39748":27164,"39749":27180,"39750":27181,"39751":27187,"39752":27203,"39753":27205,"39754":27212,"39755":27219,"39756":27223,"39757":27235,"39758":27252,"39759":27266,"39760":27274,"39761":27279,"39762":27289,"39763":27303,"39764":27313,"39765":27317,"39766":27326,"39767":27337,"39768":27348,"39769":27352,"39770":27382,"39771":27479,"39772":27514,"39773":27612,"39774":27676,"39775":27697,"39776":27736,"39777":27758,"39778":27765,"39779":27775,"39780":27823,"39781":27851,"39782":27871,"39783":27903,"39784":27906,"39785":27909,"39786":27910,"39787":27942,"39788":27991,"39789":27995,"39790":28017,"39791":28033,"39792":28047,"39793":28069,"39794":28081,"39795":28158,"39796":28162,"39797":28164,"39798":28175,"39799":28184,"39800":28202,"39801":28240,"39802":28249,"39803":28314,"39804":28341,"39805":28344,"39806":28379,"39841":28410,"39842":28420,"39843":28427,"39844":28428,"39845":28438,"39846":28439,"39847":28468,"39848":28477,"39849":28502,"39850":28537,"39851":28554,"39852":28573,"39853":28575,"39854":28603,"39855":28606,"39856":28627,"39857":28633,"39858":28664,"39859":28675,"39860":28747,"39861":28749,"39862":28752,"39863":28756,"39864":28764,"39865":28775,"39866":28791,"39867":28793,"39868":28811,"39869":28815,"39870":28832,"39871":28835,"39872":28837,"39873":28838,"39874":28839,"39875":28868,"39876":28876,"39877":28880,"39878":28886,"39879":618,"39880":603,"39881":230,"39882":652,"39883":593,"39884":596,"39885":650,"39886":605,"39887":601,"39888":602,"39889":604,"39890":609,"39891":7747,"39892":7753,"39893":330,"39894":7739,"39895":629,"39896":240,"39897":643,"39898":658,"39899":679,"39900":676,"39901":227,"39902":60294,"39903":60295,"39904":623,"39905":632,"39906":647,"39907":60299,"39908":199,"39909":339,"39910":594,"39911":65351,"39912":715,"39913":719,"39914":65345,"39915":65346,"39916":65348,"39917":65349,"39918":65350,"39919":65352,"39920":65353,"39921":65354,"39922":65355,"39923":65356,"39924":65357,"39925":65358,"39926":65359,"39927":65360,"39928":65362,"39929":65363,"39930":65364,"39931":65365,"39932":65366,"39933":65367,"39934":65370,"40000":28917,"40001":12832,"40002":12833,"40003":12834,"40004":12835,"40005":12836,"40006":12837,"40007":12838,"40008":12839,"40009":12840,"40010":12841,"40011":28926,"40012":28933,"40013":28957,"40014":28969,"40015":28971,"40016":28972,"40017":28979,"40018":28981,"40019":28987,"40020":28990,"40021":28992,"40022":29007,"40023":29035,"40024":29045,"40025":29047,"40026":29052,"40027":29054,"40028":29068,"40029":29070,"40030":29073,"40031":29078,"40032":29090,"40033":29091,"40034":29101,"40035":29108,"40036":29111,"40037":29114,"40038":29137,"40039":29149,"40040":29163,"40041":29184,"40042":29193,"40043":29198,"40044":29199,"40045":29206,"40046":29207,"40047":29220,"40048":23204,"40049":29230,"40050":8838,"40051":29271,"40052":29276,"40053":29332,"40054":29444,"40055":29456,"40056":29505,"40057":29556,"40058":29580,"40059":29583,"40060":29592,"40061":29596,"40062":29598,"40097":29607,"40098":29610,"40099":29653,"40100":29665,"40101":29666,"40102":29668,"40103":29670,"40104":29679,"40105":29683,"40106":8839,"40107":29689,"40108":29691,"40109":29698,"40110":29713,"40111":29714,"40112":29716,"40113":29717,"40114":29719,"40115":29721,"40116":29724,"40117":29726,"40118":29727,"40119":29751,"40120":29752,"40121":29753,"40122":29763,"40123":29765,"40124":29767,"40125":29768,"40126":29769,"40127":29779,"40128":29782,"40129":29797,"40130":29803,"40131":29804,"40132":29812,"40133":29818,"40134":29826,"40135":21378,"40136":24191,"40137":20008,"40138":24186,"40139":20886,"40140":23424,"40141":21353,"40142":11911,"40143":60436,"40144":21251,"40145":9746,"40146":33401,"40147":17553,"40148":11916,"40149":11914,"40150":20022,"40151":60444,"40152":21274,"40153":60446,"40154":60447,"40155":11925,"40156":60449,"40157":60450,"40158":9492,"40159":20058,"40160":36790,"40161":24308,"40162":20872,"40163":20101,"40164":60457,"40165":20031,"40166":60459,"40167":60460,"40168":20059,"40169":21430,"40170":36710,"40171":32415,"40172":35744,"40173":36125,"40174":40479,"40175":38376,"40176":38021,"40177":38429,"40178":25164,"40179":27701,"40180":20155,"40181":24516,"40182":28780,"40183":11950,"40184":21475,"40185":27362,"40186":39483,"40187":39484,"40188":39512,"40189":39516,"40190":39523,"40256":9742,"40257":8594,"40258":8592,"40259":8593,"40260":8595,"40261":8680,"40262":8678,"40263":8679,"40264":8681,"40265":8680,"40266":8678,"40267":8679,"40268":8681,"40269":9758,"40270":9756,"40271":9755,"40272":9759,"40273":12310,"40274":12311,"40275":9675,"40276":10005,"40277":10003,"40278":22267,"40279":9789,"40280":22813,"40281":26189,"40282":29221,"40283":10025,"40284":10017,"40285":9786,"40286":9785,"40287":60515,"40288":60516,"40289":60517,"40290":60518,"40291":60519,"40292":23672,"40293":9836,"40294":9834,"40295":23249,"40296":23479,"40297":23804,"40298":60526,"40299":9993,"40300":9986,"40301":60529,"40302":60530,"40303":60531,"40304":60532,"40305":23765,"40306":26478,"40307":29793,"40308":29853,"40309":32595,"40310":34195,"40311":10063,"40312":60540,"40313":60541,"40314":23928,"40315":24379,"40316":60544,"40317":9473,"40318":9475,"40353":60547,"40354":60548,"40355":60549,"40356":60550,"40357":60551,"40358":60552,"40359":60553,"40360":60554,"40361":60555,"40362":60556,"40363":60557,"40364":60558,"40365":60559,"40366":60560,"40367":60561,"40368":39602,"40369":39648,"40370":39700,"40371":39732,"40372":39737,"40373":39744,"40374":39760,"40375":39807,"40376":9788,"40377":32149,"40378":9729,"40379":38708,"40380":9730,"40381":60575,"40382":60576,"40383":60577,"40384":9992,"40385":60579,"40386":60580,"40387":60581,"40388":60582,"40389":60583,"40390":60584,"40391":60585,"40392":8507,"40393":8481,"40394":26343,"40395":28247,"40396":60590,"40397":29015,"40398":31178,"40399":8470,"40400":33132,"40401":35577,"40402":38998,"40403":60597,"40404":60598,"40405":9760,"40406":60600,"40407":9828,"40408":9824,"40409":9831,"40410":9827,"40411":9826,"40412":9830,"40413":9825,"40414":9829,"40415":60609,"40416":60610,"40417":27364,"40418":8478,"40419":13250,"40420":13272,"40421":13217,"40422":60616,"40423":13221,"40424":60618,"40425":60619,"40426":60620,"40427":60621,"40428":60622,"40429":9745,"40430":39809,"40431":39819,"40432":39821,"40433":39901,"40434":39913,"40435":39917,"40436":39924,"40437":39967,"40438":39968,"40439":39974,"40440":40019,"40441":40029,"40442":40059,"40443":40204,"40444":40214,"40445":8626,"40446":27397,"40512":36073,"40513":36082,"40514":36099,"40515":36113,"40516":36124,"40517":36218,"40518":36265,"40519":36288,"40520":36353,"40521":36366,"40522":36422,"40523":36456,"40524":36465,"40525":36478,"40526":36480,"40527":36534,"40528":36537,"40529":36540,"40530":36547,"40531":36580,"40532":36589,"40533":36594,"40534":36656,"40535":36673,"40536":36682,"40537":36773,"40538":36787,"40539":36792,"40540":36810,"40541":36815,"40542":36872,"40543":36915,"40544":36919,"40545":36964,"40546":36972,"40547":37289,"40548":37302,"40549":37316,"40550":37370,"40551":37384,"40552":37395,"40553":37409,"40554":37416,"40555":37419,"40556":37429,"40557":37436,"40558":37441,"40559":37464,"40560":37469,"40561":37471,"40562":37483,"40563":37486,"40564":37505,"40565":37508,"40566":37513,"40567":37519,"40568":37553,"40569":37562,"40570":37567,"40571":37588,"40572":37595,"40573":37603,"40574":37605,"40609":37611,"40610":37612,"40611":37620,"40612":37622,"40613":37629,"40614":37635,"40615":37639,"40616":37680,"40617":37681,"40618":37696,"40619":37698,"40620":37699,"40621":37727,"40622":37730,"40623":37734,"40624":37736,"40625":37747,"40626":37748,"40627":37752,"40628":37757,"40629":37761,"40630":37764,"40631":37766,"40632":37767,"40633":37776,"40634":37788,"40635":37792,"40636":37816,"40637":37819,"40638":37821,"40639":37823,"40640":37835,"40641":37843,"40642":37851,"40643":37856,"40644":37872,"40645":37873,"40646":37875,"40647":37876,"40648":37889,"40649":37892,"40650":37896,"40651":37911,"40652":37915,"40653":37917,"40654":37924,"40655":37925,"40656":37926,"40657":37933,"40658":37954,"40659":37955,"40660":37965,"40661":37972,"40662":37976,"40663":37989,"40664":37991,"40665":37996,"40666":38009,"40667":38011,"40668":38264,"40669":38277,"40670":38310,"40671":38314,"40672":38486,"40673":38523,"40674":38565,"40675":38644,"40676":38683,"40677":38710,"40678":38720,"40679":38721,"40680":38743,"40681":38791,"40682":38793,"40683":38811,"40684":38833,"40685":38845,"40686":38848,"40687":38850,"40688":38866,"40689":38880,"40690":38932,"40691":38933,"40692":38947,"40693":38963,"40694":39016,"40695":39095,"40696":39097,"40697":39111,"40698":39114,"40699":39136,"40700":39137,"40701":39148,"40702":39157,"40768":40225,"40769":40244,"40770":40249,"40771":40265,"40772":40270,"40773":40301,"40774":8759,"40775":40302,"40776":40316,"40777":40323,"40778":40339,"40779":40357,"40780":8748,"40781":40381,"40782":27521,"40783":27569,"40784":40015,"40785":40592,"40786":40384,"40787":60817,"40788":60818,"40789":9775,"40790":9776,"40791":9783,"40792":9779,"40793":9780,"40794":9781,"40795":9778,"40796":9782,"40797":9777,"40798":40393,"40799":40404,"40800":40444,"40801":40458,"40802":40460,"40803":40462,"40804":40472,"40805":40571,"40806":40581,"40807":40610,"40808":40620,"40809":40625,"40810":40641,"40811":40646,"40812":40647,"40813":40689,"40814":40696,"40815":40743,"40816":39182,"40817":39193,"40818":39196,"40819":39223,"40820":39261,"40821":39266,"40822":39323,"40823":39332,"40824":39338,"40825":39352,"40826":39392,"40827":39398,"40828":39413,"40829":39455,"40830":32254,"40865":32263,"40866":32347,"40867":32357,"40868":32364,"40869":32567,"40870":32576,"40871":32577,"40872":32585,"40873":32594,"40874":32655,"40875":32659,"40876":32692,"40877":32733,"40878":32743,"40879":32762,"40880":32770,"40881":32776,"40882":32814,"40883":32815,"40884":32828,"40885":32935,"40886":33036,"40887":33066,"40888":33076,"40889":33090,"40890":33110,"40891":33156,"40892":33189,"40893":33252,"40894":33364,"40895":33381,"40896":33403,"40897":33415,"40898":33471,"40899":33506,"40900":33518,"40901":33528,"40902":33532,"40903":33535,"40904":33547,"40905":33565,"40906":33597,"40907":33623,"40908":33681,"40909":33708,"40910":33741,"40911":33773,"40912":33797,"40913":33812,"40914":33814,"40915":33825,"40916":33838,"40917":33854,"40918":33866,"40919":33875,"40920":33877,"40921":33880,"40922":33892,"40923":33906,"40924":33919,"40925":33920,"40926":33938,"40927":33939,"40928":33942,"40929":33955,"40930":33982,"40931":34014,"40932":34017,"40933":34018,"40934":34020,"40935":34040,"40936":34051,"40937":34053,"40938":34064,"40939":34099,"40940":8208,"40941":34114,"40942":34124,"40943":34130,"40944":34143,"40945":34159,"40946":34160,"40947":34163,"40948":34262,"40949":34272,"40950":34286,"40951":34300,"40952":34317,"40953":34319,"40954":34324,"40955":34344,"40956":34370,"40957":34373,"40958":34418,"41024":34972,"41025":23405,"41026":33079,"41027":60958,"41028":39224,"41029":21874,"41030":21867,"41031":60962,"41032":13774,"41033":21873,"41034":21946,"41035":22001,"41036":13778,"41037":22000,"41038":22021,"41039":22050,"41040":22061,"41041":22083,"41042":22046,"41043":22162,"41044":31949,"41045":21530,"41046":21523,"41047":21655,"41048":26353,"41049":30004,"41050":21581,"41051":22180,"41052":22175,"41053":25811,"41054":25390,"41055":25592,"41056":25886,"41057":20088,"41058":27626,"41059":27698,"41060":27709,"41061":27746,"41062":27826,"41063":28152,"41064":28201,"41065":28278,"41066":28290,"41067":28294,"41068":28347,"41069":28383,"41070":28386,"41071":28433,"41072":28452,"41073":28532,"41074":28561,"41075":28597,"41076":28659,"41077":28661,"41078":28859,"41079":28864,"41080":28943,"41081":8706,"41082":29013,"41083":29043,"41084":29050,"41085":61016,"41086":21027,"41121":61018,"41122":13393,"41123":61020,"41124":36812,"41125":61022,"41126":61023,"41127":192,"41128":200,"41129":204,"41130":210,"41131":217,"41132":193,"41133":205,"41134":211,"41135":218,"41136":257,"41137":275,"41138":299,"41139":333,"41140":363,"41141":470,"41142":196,"41143":203,"41144":207,"41145":214,"41146":220,"41147":198,"41148":199,"41149":209,"41150":195,"41151":213,"41152":225,"41153":233,"41154":237,"41155":243,"41156":250,"41157":472,"41158":228,"41159":235,"41160":239,"41161":246,"41162":252,"41163":230,"41164":231,"41165":241,"41166":227,"41167":245,"41168":462,"41169":283,"41170":464,"41171":466,"41172":468,"41173":474,"41174":197,"41175":201,"41176":29064,"41177":216,"41178":208,"41179":7922,"41180":222,"41181":223,"41182":170,"41183":161,"41184":224,"41185":232,"41186":236,"41187":242,"41188":249,"41189":476,"41190":229,"41191":29080,"41192":29143,"41193":248,"41194":240,"41195":7923,"41196":254,"41197":255,"41198":186,"41199":191,"41200":226,"41201":234,"41202":238,"41203":244,"41204":251,"41205":29173,"41206":194,"41207":202,"41208":206,"41209":212,"41210":219,"41211":184,"41212":164,"41213":61110,"41214":402,"41280":12288,"41281":65292,"41282":12289,"41283":12290,"41284":65294,"41285":8231,"41286":65307,"41287":65306,"41288":65311,"41289":65281,"41290":65072,"41291":8230,"41292":8229,"41293":65104,"41294":65105,"41295":65106,"41296":183,"41297":65108,"41298":65109,"41299":65110,"41300":65111,"41301":65372,"41302":8211,"41303":65073,"41304":8212,"41305":65075,"41306":9588,"41307":65076,"41308":65103,"41309":65288,"41310":65289,"41311":65077,"41312":65078,"41313":65371,"41314":65373,"41315":65079,"41316":65080,"41317":12308,"41318":12309,"41319":65081,"41320":65082,"41321":12304,"41322":12305,"41323":65083,"41324":65084,"41325":12298,"41326":12299,"41327":65085,"41328":65086,"41329":12296,"41330":12297,"41331":65087,"41332":65088,"41333":12300,"41334":12301,"41335":65089,"41336":65090,"41337":12302,"41338":12303,"41339":65091,"41340":65092,"41341":65113,"41342":65114,"41377":65115,"41378":65116,"41379":65117,"41380":65118,"41381":8216,"41382":8217,"41383":8220,"41384":8221,"41385":12317,"41386":12318,"41387":8245,"41388":8242,"41389":65283,"41390":65286,"41391":65290,"41392":8251,"41393":167,"41394":12291,"41395":9675,"41396":9679,"41397":9651,"41398":9650,"41399":9678,"41400":9734,"41401":9733,"41402":9671,"41403":9670,"41404":9633,"41405":9632,"41406":9661,"41407":9660,"41408":12963,"41409":8453,"41410":175,"41411":65507,"41412":65343,"41413":717,"41414":65097,"41415":65098,"41416":65101,"41417":65102,"41418":65099,"41419":65100,"41420":65119,"41421":65120,"41422":65121,"41423":65291,"41424":65293,"41425":215,"41426":247,"41427":177,"41428":8730,"41429":65308,"41430":65310,"41431":65309,"41432":8806,"41433":8807,"41434":8800,"41435":8734,"41436":8786,"41437":8801,"41438":65122,"41439":65123,"41440":65124,"41441":65125,"41442":65126,"41443":65374,"41444":8745,"41445":8746,"41446":8869,"41447":8736,"41448":8735,"41449":8895,"41450":13266,"41451":13265,"41452":8747,"41453":8750,"41454":8757,"41455":8756,"41456":9792,"41457":9794,"41458":8853,"41459":8857,"41460":8593,"41461":8595,"41462":8592,"41463":8594,"41464":8598,"41465":8599,"41466":8601,"41467":8600,"41468":8741,"41469":8739,"41470":65295,"41536":65340,"41537":8725,"41538":65128,"41539":65284,"41540":65509,"41541":12306,"41542":65504,"41543":65505,"41544":65285,"41545":65312,"41546":8451,"41547":8457,"41548":65129,"41549":65130,"41550":65131,"41551":13269,"41552":13212,"41553":13213,"41554":13214,"41555":13262,"41556":13217,"41557":13198,"41558":13199,"41559":13252,"41560":176,"41561":20825,"41562":20827,"41563":20830,"41564":20829,"41565":20833,"41566":20835,"41567":21991,"41568":29929,"41569":31950,"41570":9601,"41571":9602,"41572":9603,"41573":9604,"41574":9605,"41575":9606,"41576":9607,"41577":9608,"41578":9615,"41579":9614,"41580":9613,"41581":9612,"41582":9611,"41583":9610,"41584":9609,"41585":9532,"41586":9524,"41587":9516,"41588":9508,"41589":9500,"41590":9620,"41591":9472,"41592":9474,"41593":9621,"41594":9484,"41595":9488,"41596":9492,"41597":9496,"41598":9581,"41633":9582,"41634":9584,"41635":9583,"41636":9552,"41637":9566,"41638":9578,"41639":9569,"41640":9698,"41641":9699,"41642":9701,"41643":9700,"41644":9585,"41645":9586,"41646":9587,"41647":65296,"41648":65297,"41649":65298,"41650":65299,"41651":65300,"41652":65301,"41653":65302,"41654":65303,"41655":65304,"41656":65305,"41657":8544,"41658":8545,"41659":8546,"41660":8547,"41661":8548,"41662":8549,"41663":8550,"41664":8551,"41665":8552,"41666":8553,"41667":12321,"41668":12322,"41669":12323,"41670":12324,"41671":12325,"41672":12326,"41673":12327,"41674":12328,"41675":12329,"41676":21313,"41677":21316,"41678":21317,"41679":65313,"41680":65314,"41681":65315,"41682":65316,"41683":65317,"41684":65318,"41685":65319,"41686":65320,"41687":65321,"41688":65322,"41689":65323,"41690":65324,"41691":65325,"41692":65326,"41693":65327,"41694":65328,"41695":65329,"41696":65330,"41697":65331,"41698":65332,"41699":65333,"41700":65334,"41701":65335,"41702":65336,"41703":65337,"41704":65338,"41705":65345,"41706":65346,"41707":65347,"41708":65348,"41709":65349,"41710":65350,"41711":65351,"41712":65352,"41713":65353,"41714":65354,"41715":65355,"41716":65356,"41717":65357,"41718":65358,"41719":65359,"41720":65360,"41721":65361,"41722":65362,"41723":65363,"41724":65364,"41725":65365,"41726":65366,"41792":65367,"41793":65368,"41794":65369,"41795":65370,"41796":913,"41797":914,"41798":915,"41799":916,"41800":917,"41801":918,"41802":919,"41803":920,"41804":921,"41805":922,"41806":923,"41807":924,"41808":925,"41809":926,"41810":927,"41811":928,"41812":929,"41813":931,"41814":932,"41815":933,"41816":934,"41817":935,"41818":936,"41819":937,"41820":945,"41821":946,"41822":947,"41823":948,"41824":949,"41825":950,"41826":951,"41827":952,"41828":953,"41829":954,"41830":955,"41831":956,"41832":957,"41833":958,"41834":959,"41835":960,"41836":961,"41837":963,"41838":964,"41839":965,"41840":966,"41841":967,"41842":968,"41843":969,"41844":12549,"41845":12550,"41846":12551,"41847":12552,"41848":12553,"41849":12554,"41850":12555,"41851":12556,"41852":12557,"41853":12558,"41854":12559,"41889":12560,"41890":12561,"41891":12562,"41892":12563,"41893":12564,"41894":12565,"41895":12566,"41896":12567,"41897":12568,"41898":12569,"41899":12570,"41900":12571,"41901":12572,"41902":12573,"41903":12574,"41904":12575,"41905":12576,"41906":12577,"41907":12578,"41908":12579,"41909":12580,"41910":12581,"41911":12582,"41912":12583,"41913":12584,"41914":12585,"41915":729,"41916":713,"41917":714,"41918":711,"41919":715,"41920":9216,"41921":9217,"41922":9218,"41923":9219,"41924":9220,"41925":9221,"41926":9222,"41927":9223,"41928":9224,"41929":9225,"41930":9226,"41931":9227,"41932":9228,"41933":9229,"41934":9230,"41935":9231,"41936":9232,"41937":9233,"41938":9234,"41939":9235,"41940":9236,"41941":9237,"41942":9238,"41943":9239,"41944":9240,"41945":9241,"41946":9242,"41947":9243,"41948":9244,"41949":9245,"41950":9246,"41951":9247,"41952":9249,"41953":8364,"41954":63561,"41955":63562,"41956":63563,"41957":63564,"41958":63565,"41959":63566,"41960":63567,"41961":63568,"41962":63569,"41963":63570,"41964":63571,"41965":63572,"41966":63573,"41967":63574,"41968":63575,"41969":63576,"41970":63577,"41971":63578,"41972":63579,"41973":63580,"41974":63581,"41975":63582,"41976":63583,"41977":63584,"41978":63585,"41979":63586,"41980":63587,"41981":63588,"41982":63589,"42048":19968,"42049":20057,"42050":19969,"42051":19971,"42052":20035,"42053":20061,"42054":20102,"42055":20108,"42056":20154,"42057":20799,"42058":20837,"42059":20843,"42060":20960,"42061":20992,"42062":20993,"42063":21147,"42064":21269,"42065":21313,"42066":21340,"42067":21448,"42068":19977,"42069":19979,"42070":19976,"42071":19978,"42072":20011,"42073":20024,"42074":20961,"42075":20037,"42076":20040,"42077":20063,"42078":20062,"42079":20110,"42080":20129,"42081":20800,"42082":20995,"42083":21242,"42084":21315,"42085":21449,"42086":21475,"42087":22303,"42088":22763,"42089":22805,"42090":22823,"42091":22899,"42092":23376,"42093":23377,"42094":23379,"42095":23544,"42096":23567,"42097":23586,"42098":23608,"42099":23665,"42100":24029,"42101":24037,"42102":24049,"42103":24050,"42104":24051,"42105":24062,"42106":24178,"42107":24318,"42108":24331,"42109":24339,"42110":25165,"42145":19985,"42146":19984,"42147":19981,"42148":20013,"42149":20016,"42150":20025,"42151":20043,"42152":23609,"42153":20104,"42154":20113,"42155":20117,"42156":20114,"42157":20116,"42158":20130,"42159":20161,"42160":20160,"42161":20163,"42162":20166,"42163":20167,"42164":20173,"42165":20170,"42166":20171,"42167":20164,"42168":20803,"42169":20801,"42170":20839,"42171":20845,"42172":20846,"42173":20844,"42174":20887,"42175":20982,"42176":20998,"42177":20999,"42178":21000,"42179":21243,"42180":21246,"42181":21247,"42182":21270,"42183":21305,"42184":21320,"42185":21319,"42186":21317,"42187":21342,"42188":21380,"42189":21451,"42190":21450,"42191":21453,"42192":22764,"42193":22825,"42194":22827,"42195":22826,"42196":22829,"42197":23380,"42198":23569,"42199":23588,"42200":23610,"42201":23663,"42202":24052,"42203":24187,"42204":24319,"42205":24340,"42206":24341,"42207":24515,"42208":25096,"42209":25142,"42210":25163,"42211":25166,"42212":25903,"42213":25991,"42214":26007,"42215":26020,"42216":26041,"42217":26085,"42218":26352,"42219":26376,"42220":26408,"42221":27424,"42222":27490,"42223":27513,"42224":27595,"42225":27604,"42226":27611,"42227":27663,"42228":27700,"42229":28779,"42230":29226,"42231":29238,"42232":29243,"42233":29255,"42234":29273,"42235":29275,"42236":29356,"42237":29579,"42238":19993,"42304":19990,"42305":19989,"42306":19988,"42307":19992,"42308":20027,"42309":20045,"42310":20047,"42311":20046,"42312":20197,"42313":20184,"42314":20180,"42315":20181,"42316":20182,"42317":20183,"42318":20195,"42319":20196,"42320":20185,"42321":20190,"42322":20805,"42323":20804,"42324":20873,"42325":20874,"42326":20908,"42327":20985,"42328":20986,"42329":20984,"42330":21002,"42331":21152,"42332":21151,"42333":21253,"42334":21254,"42335":21271,"42336":21277,"42337":20191,"42338":21322,"42339":21321,"42340":21345,"42341":21344,"42342":21359,"42343":21358,"42344":21435,"42345":21487,"42346":21476,"42347":21491,"42348":21484,"42349":21486,"42350":21481,"42351":21480,"42352":21500,"42353":21496,"42354":21493,"42355":21483,"42356":21478,"42357":21482,"42358":21490,"42359":21489,"42360":21488,"42361":21477,"42362":21485,"42363":21499,"42364":22235,"42365":22234,"42366":22806,"42401":22830,"42402":22833,"42403":22900,"42404":22902,"42405":23381,"42406":23427,"42407":23612,"42408":24040,"42409":24039,"42410":24038,"42411":24066,"42412":24067,"42413":24179,"42414":24188,"42415":24321,"42416":24344,"42417":24343,"42418":24517,"42419":25098,"42420":25171,"42421":25172,"42422":25170,"42423":25169,"42424":26021,"42425":26086,"42426":26414,"42427":26412,"42428":26410,"42429":26411,"42430":26413,"42431":27491,"42432":27597,"42433":27665,"42434":27664,"42435":27704,"42436":27713,"42437":27712,"42438":27710,"42439":29359,"42440":29572,"42441":29577,"42442":29916,"42443":29926,"42444":29976,"42445":29983,"42446":29992,"42447":29993,"42448":30000,"42449":30001,"42450":30002,"42451":30003,"42452":30091,"42453":30333,"42454":30382,"42455":30399,"42456":30446,"42457":30683,"42458":30690,"42459":30707,"42460":31034,"42461":31166,"42462":31348,"42463":31435,"42464":19998,"42465":19999,"42466":20050,"42467":20051,"42468":20073,"42469":20121,"42470":20132,"42471":20134,"42472":20133,"42473":20223,"42474":20233,"42475":20249,"42476":20234,"42477":20245,"42478":20237,"42479":20240,"42480":20241,"42481":20239,"42482":20210,"42483":20214,"42484":20219,"42485":20208,"42486":20211,"42487":20221,"42488":20225,"42489":20235,"42490":20809,"42491":20807,"42492":20806,"42493":20808,"42494":20840,"42560":20849,"42561":20877,"42562":20912,"42563":21015,"42564":21009,"42565":21010,"42566":21006,"42567":21014,"42568":21155,"42569":21256,"42570":21281,"42571":21280,"42572":21360,"42573":21361,"42574":21513,"42575":21519,"42576":21516,"42577":21514,"42578":21520,"42579":21505,"42580":21515,"42581":21508,"42582":21521,"42583":21517,"42584":21512,"42585":21507,"42586":21518,"42587":21510,"42588":21522,"42589":22240,"42590":22238,"42591":22237,"42592":22323,"42593":22320,"42594":22312,"42595":22317,"42596":22316,"42597":22319,"42598":22313,"42599":22809,"42600":22810,"42601":22839,"42602":22840,"42603":22916,"42604":22904,"42605":22915,"42606":22909,"42607":22905,"42608":22914,"42609":22913,"42610":23383,"42611":23384,"42612":23431,"42613":23432,"42614":23429,"42615":23433,"42616":23546,"42617":23574,"42618":23673,"42619":24030,"42620":24070,"42621":24182,"42622":24180,"42657":24335,"42658":24347,"42659":24537,"42660":24534,"42661":25102,"42662":25100,"42663":25101,"42664":25104,"42665":25187,"42666":25179,"42667":25176,"42668":25910,"42669":26089,"42670":26088,"42671":26092,"42672":26093,"42673":26354,"42674":26355,"42675":26377,"42676":26429,"42677":26420,"42678":26417,"42679":26421,"42680":27425,"42681":27492,"42682":27515,"42683":27670,"42684":27741,"42685":27735,"42686":27737,"42687":27743,"42688":27744,"42689":27728,"42690":27733,"42691":27745,"42692":27739,"42693":27725,"42694":27726,"42695":28784,"42696":29279,"42697":29277,"42698":30334,"42699":31481,"42700":31859,"42701":31992,"42702":32566,"42703":32650,"42704":32701,"42705":32769,"42706":32771,"42707":32780,"42708":32786,"42709":32819,"42710":32895,"42711":32905,"42712":32907,"42713":32908,"42714":33251,"42715":33258,"42716":33267,"42717":33276,"42718":33292,"42719":33307,"42720":33311,"42721":33390,"42722":33394,"42723":33406,"42724":34411,"42725":34880,"42726":34892,"42727":34915,"42728":35199,"42729":38433,"42730":20018,"42731":20136,"42732":20301,"42733":20303,"42734":20295,"42735":20311,"42736":20318,"42737":20276,"42738":20315,"42739":20309,"42740":20272,"42741":20304,"42742":20305,"42743":20285,"42744":20282,"42745":20280,"42746":20291,"42747":20308,"42748":20284,"42749":20294,"42750":20323,"42816":20316,"42817":20320,"42818":20271,"42819":20302,"42820":20278,"42821":20313,"42822":20317,"42823":20296,"42824":20314,"42825":20812,"42826":20811,"42827":20813,"42828":20853,"42829":20918,"42830":20919,"42831":21029,"42832":21028,"42833":21033,"42834":21034,"42835":21032,"42836":21163,"42837":21161,"42838":21162,"42839":21164,"42840":21283,"42841":21363,"42842":21365,"42843":21533,"42844":21549,"42845":21534,"42846":21566,"42847":21542,"42848":21582,"42849":21543,"42850":21574,"42851":21571,"42852":21555,"42853":21576,"42854":21570,"42855":21531,"42856":21545,"42857":21578,"42858":21561,"42859":21563,"42860":21560,"42861":21550,"42862":21557,"42863":21558,"42864":21536,"42865":21564,"42866":21568,"42867":21553,"42868":21547,"42869":21535,"42870":21548,"42871":22250,"42872":22256,"42873":22244,"42874":22251,"42875":22346,"42876":22353,"42877":22336,"42878":22349,"42913":22343,"42914":22350,"42915":22334,"42916":22352,"42917":22351,"42918":22331,"42919":22767,"42920":22846,"42921":22941,"42922":22930,"42923":22952,"42924":22942,"42925":22947,"42926":22937,"42927":22934,"42928":22925,"42929":22948,"42930":22931,"42931":22922,"42932":22949,"42933":23389,"42934":23388,"42935":23386,"42936":23387,"42937":23436,"42938":23435,"42939":23439,"42940":23596,"42941":23616,"42942":23617,"42943":23615,"42944":23614,"42945":23696,"42946":23697,"42947":23700,"42948":23692,"42949":24043,"42950":24076,"42951":24207,"42952":24199,"42953":24202,"42954":24311,"42955":24324,"42956":24351,"42957":24420,"42958":24418,"42959":24439,"42960":24441,"42961":24536,"42962":24524,"42963":24535,"42964":24525,"42965":24561,"42966":24555,"42967":24568,"42968":24554,"42969":25106,"42970":25105,"42971":25220,"42972":25239,"42973":25238,"42974":25216,"42975":25206,"42976":25225,"42977":25197,"42978":25226,"42979":25212,"42980":25214,"42981":25209,"42982":25203,"42983":25234,"42984":25199,"42985":25240,"42986":25198,"42987":25237,"42988":25235,"42989":25233,"42990":25222,"42991":25913,"42992":25915,"42993":25912,"42994":26097,"42995":26356,"42996":26463,"42997":26446,"42998":26447,"42999":26448,"43000":26449,"43001":26460,"43002":26454,"43003":26462,"43004":26441,"43005":26438,"43006":26464,"43072":26451,"43073":26455,"43074":27493,"43075":27599,"43076":27714,"43077":27742,"43078":27801,"43079":27777,"43080":27784,"43081":27785,"43082":27781,"43083":27803,"43084":27754,"43085":27770,"43086":27792,"43087":27760,"43088":27788,"43089":27752,"43090":27798,"43091":27794,"43092":27773,"43093":27779,"43094":27762,"43095":27774,"43096":27764,"43097":27782,"43098":27766,"43099":27789,"43100":27796,"43101":27800,"43102":27778,"43103":28790,"43104":28796,"43105":28797,"43106":28792,"43107":29282,"43108":29281,"43109":29280,"43110":29380,"43111":29378,"43112":29590,"43113":29996,"43114":29995,"43115":30007,"43116":30008,"43117":30338,"43118":30447,"43119":30691,"43120":31169,"43121":31168,"43122":31167,"43123":31350,"43124":31995,"43125":32597,"43126":32918,"43127":32915,"43128":32925,"43129":32920,"43130":32923,"43131":32922,"43132":32946,"43133":33391,"43134":33426,"43169":33419,"43170":33421,"43171":35211,"43172":35282,"43173":35328,"43174":35895,"43175":35910,"43176":35925,"43177":35997,"43178":36196,"43179":36208,"43180":36275,"43181":36523,"43182":36554,"43183":36763,"43184":36784,"43185":36802,"43186":36806,"43187":36805,"43188":36804,"43189":24033,"43190":37009,"43191":37026,"43192":37034,"43193":37030,"43194":37027,"43195":37193,"43196":37318,"43197":37324,"43198":38450,"43199":38446,"43200":38449,"43201":38442,"43202":38444,"43203":20006,"43204":20054,"43205":20083,"43206":20107,"43207":20123,"43208":20126,"43209":20139,"43210":20140,"43211":20335,"43212":20381,"43213":20365,"43214":20339,"43215":20351,"43216":20332,"43217":20379,"43218":20363,"43219":20358,"43220":20355,"43221":20336,"43222":20341,"43223":20360,"43224":20329,"43225":20347,"43226":20374,"43227":20350,"43228":20367,"43229":20369,"43230":20346,"43231":20820,"43232":20818,"43233":20821,"43234":20841,"43235":20855,"43236":20854,"43237":20856,"43238":20925,"43239":20989,"43240":21051,"43241":21048,"43242":21047,"43243":21050,"43244":21040,"43245":21038,"43246":21046,"43247":21057,"43248":21182,"43249":21179,"43250":21330,"43251":21332,"43252":21331,"43253":21329,"43254":21350,"43255":21367,"43256":21368,"43257":21369,"43258":21462,"43259":21460,"43260":21463,"43261":21619,"43262":21621,"43328":21654,"43329":21624,"43330":21653,"43331":21632,"43332":21627,"43333":21623,"43334":21636,"43335":21650,"43336":21638,"43337":21628,"43338":21648,"43339":21617,"43340":21622,"43341":21644,"43342":21658,"43343":21602,"43344":21608,"43345":21643,"43346":21629,"43347":21646,"43348":22266,"43349":22403,"43350":22391,"43351":22378,"43352":22377,"43353":22369,"43354":22374,"43355":22372,"43356":22396,"43357":22812,"43358":22857,"43359":22855,"43360":22856,"43361":22852,"43362":22868,"43363":22974,"43364":22971,"43365":22996,"43366":22969,"43367":22958,"43368":22993,"43369":22982,"43370":22992,"43371":22989,"43372":22987,"43373":22995,"43374":22986,"43375":22959,"43376":22963,"43377":22994,"43378":22981,"43379":23391,"43380":23396,"43381":23395,"43382":23447,"43383":23450,"43384":23448,"43385":23452,"43386":23449,"43387":23451,"43388":23578,"43389":23624,"43390":23621,"43425":23622,"43426":23735,"43427":23713,"43428":23736,"43429":23721,"43430":23723,"43431":23729,"43432":23731,"43433":24088,"43434":24090,"43435":24086,"43436":24085,"43437":24091,"43438":24081,"43439":24184,"43440":24218,"43441":24215,"43442":24220,"43443":24213,"43444":24214,"43445":24310,"43446":24358,"43447":24359,"43448":24361,"43449":24448,"43450":24449,"43451":24447,"43452":24444,"43453":24541,"43454":24544,"43455":24573,"43456":24565,"43457":24575,"43458":24591,"43459":24596,"43460":24623,"43461":24629,"43462":24598,"43463":24618,"43464":24597,"43465":24609,"43466":24615,"43467":24617,"43468":24619,"43469":24603,"43470":25110,"43471":25109,"43472":25151,"43473":25150,"43474":25152,"43475":25215,"43476":25289,"43477":25292,"43478":25284,"43479":25279,"43480":25282,"43481":25273,"43482":25298,"43483":25307,"43484":25259,"43485":25299,"43486":25300,"43487":25291,"43488":25288,"43489":25256,"43490":25277,"43491":25276,"43492":25296,"43493":25305,"43494":25287,"43495":25293,"43496":25269,"43497":25306,"43498":25265,"43499":25304,"43500":25302,"43501":25303,"43502":25286,"43503":25260,"43504":25294,"43505":25918,"43506":26023,"43507":26044,"43508":26106,"43509":26132,"43510":26131,"43511":26124,"43512":26118,"43513":26114,"43514":26126,"43515":26112,"43516":26127,"43517":26133,"43518":26122,"43584":26119,"43585":26381,"43586":26379,"43587":26477,"43588":26507,"43589":26517,"43590":26481,"43591":26524,"43592":26483,"43593":26487,"43594":26503,"43595":26525,"43596":26519,"43597":26479,"43598":26480,"43599":26495,"43600":26505,"43601":26494,"43602":26512,"43603":26485,"43604":26522,"43605":26515,"43606":26492,"43607":26474,"43608":26482,"43609":27427,"43610":27494,"43611":27495,"43612":27519,"43613":27667,"43614":27675,"43615":27875,"43616":27880,"43617":27891,"43618":27825,"43619":27852,"43620":27877,"43621":27827,"43622":27837,"43623":27838,"43624":27836,"43625":27874,"43626":27819,"43627":27861,"43628":27859,"43629":27832,"43630":27844,"43631":27833,"43632":27841,"43633":27822,"43634":27863,"43635":27845,"43636":27889,"43637":27839,"43638":27835,"43639":27873,"43640":27867,"43641":27850,"43642":27820,"43643":27887,"43644":27868,"43645":27862,"43646":27872,"43681":28821,"43682":28814,"43683":28818,"43684":28810,"43685":28825,"43686":29228,"43687":29229,"43688":29240,"43689":29256,"43690":29287,"43691":29289,"43692":29376,"43693":29390,"43694":29401,"43695":29399,"43696":29392,"43697":29609,"43698":29608,"43699":29599,"43700":29611,"43701":29605,"43702":30013,"43703":30109,"43704":30105,"43705":30106,"43706":30340,"43707":30402,"43708":30450,"43709":30452,"43710":30693,"43711":30717,"43712":31038,"43713":31040,"43714":31041,"43715":31177,"43716":31176,"43717":31354,"43718":31353,"43719":31482,"43720":31998,"43721":32596,"43722":32652,"43723":32651,"43724":32773,"43725":32954,"43726":32933,"43727":32930,"43728":32945,"43729":32929,"43730":32939,"43731":32937,"43732":32948,"43733":32938,"43734":32943,"43735":33253,"43736":33278,"43737":33293,"43738":33459,"43739":33437,"43740":33433,"43741":33453,"43742":33469,"43743":33439,"43744":33465,"43745":33457,"43746":33452,"43747":33445,"43748":33455,"43749":33464,"43750":33443,"43751":33456,"43752":33470,"43753":33463,"43754":34382,"43755":34417,"43756":21021,"43757":34920,"43758":36555,"43759":36814,"43760":36820,"43761":36817,"43762":37045,"43763":37048,"43764":37041,"43765":37046,"43766":37319,"43767":37329,"43768":38263,"43769":38272,"43770":38428,"43771":38464,"43772":38463,"43773":38459,"43774":38468,"43840":38466,"43841":38585,"43842":38632,"43843":38738,"43844":38750,"43845":20127,"43846":20141,"43847":20142,"43848":20449,"43849":20405,"43850":20399,"43851":20415,"43852":20448,"43853":20433,"43854":20431,"43855":20445,"43856":20419,"43857":20406,"43858":20440,"43859":20447,"43860":20426,"43861":20439,"43862":20398,"43863":20432,"43864":20420,"43865":20418,"43866":20442,"43867":20430,"43868":20446,"43869":20407,"43870":20823,"43871":20882,"43872":20881,"43873":20896,"43874":21070,"43875":21059,"43876":21066,"43877":21069,"43878":21068,"43879":21067,"43880":21063,"43881":21191,"43882":21193,"43883":21187,"43884":21185,"43885":21261,"43886":21335,"43887":21371,"43888":21402,"43889":21467,"43890":21676,"43891":21696,"43892":21672,"43893":21710,"43894":21705,"43895":21688,"43896":21670,"43897":21683,"43898":21703,"43899":21698,"43900":21693,"43901":21674,"43902":21697,"43937":21700,"43938":21704,"43939":21679,"43940":21675,"43941":21681,"43942":21691,"43943":21673,"43944":21671,"43945":21695,"43946":22271,"43947":22402,"43948":22411,"43949":22432,"43950":22435,"43951":22434,"43952":22478,"43953":22446,"43954":22419,"43955":22869,"43956":22865,"43957":22863,"43958":22862,"43959":22864,"43960":23004,"43961":23000,"43962":23039,"43963":23011,"43964":23016,"43965":23043,"43966":23013,"43967":23018,"43968":23002,"43969":23014,"43970":23041,"43971":23035,"43972":23401,"43973":23459,"43974":23462,"43975":23460,"43976":23458,"43977":23461,"43978":23553,"43979":23630,"43980":23631,"43981":23629,"43982":23627,"43983":23769,"43984":23762,"43985":24055,"43986":24093,"43987":24101,"43988":24095,"43989":24189,"43990":24224,"43991":24230,"43992":24314,"43993":24328,"43994":24365,"43995":24421,"43996":24456,"43997":24453,"43998":24458,"43999":24459,"44000":24455,"44001":24460,"44002":24457,"44003":24594,"44004":24605,"44005":24608,"44006":24613,"44007":24590,"44008":24616,"44009":24653,"44010":24688,"44011":24680,"44012":24674,"44013":24646,"44014":24643,"44015":24684,"44016":24683,"44017":24682,"44018":24676,"44019":25153,"44020":25308,"44021":25366,"44022":25353,"44023":25340,"44024":25325,"44025":25345,"44026":25326,"44027":25341,"44028":25351,"44029":25329,"44030":25335,"44096":25327,"44097":25324,"44098":25342,"44099":25332,"44100":25361,"44101":25346,"44102":25919,"44103":25925,"44104":26027,"44105":26045,"44106":26082,"44107":26149,"44108":26157,"44109":26144,"44110":26151,"44111":26159,"44112":26143,"44113":26152,"44114":26161,"44115":26148,"44116":26359,"44117":26623,"44118":26579,"44119":26609,"44120":26580,"44121":26576,"44122":26604,"44123":26550,"44124":26543,"44125":26613,"44126":26601,"44127":26607,"44128":26564,"44129":26577,"44130":26548,"44131":26586,"44132":26597,"44133":26552,"44134":26575,"44135":26590,"44136":26611,"44137":26544,"44138":26585,"44139":26594,"44140":26589,"44141":26578,"44142":27498,"44143":27523,"44144":27526,"44145":27573,"44146":27602,"44147":27607,"44148":27679,"44149":27849,"44150":27915,"44151":27954,"44152":27946,"44153":27969,"44154":27941,"44155":27916,"44156":27953,"44157":27934,"44158":27927,"44193":27963,"44194":27965,"44195":27966,"44196":27958,"44197":27931,"44198":27893,"44199":27961,"44200":27943,"44201":27960,"44202":27945,"44203":27950,"44204":27957,"44205":27918,"44206":27947,"44207":28843,"44208":28858,"44209":28851,"44210":28844,"44211":28847,"44212":28845,"44213":28856,"44214":28846,"44215":28836,"44216":29232,"44217":29298,"44218":29295,"44219":29300,"44220":29417,"44221":29408,"44222":29409,"44223":29623,"44224":29642,"44225":29627,"44226":29618,"44227":29645,"44228":29632,"44229":29619,"44230":29978,"44231":29997,"44232":30031,"44233":30028,"44234":30030,"44235":30027,"44236":30123,"44237":30116,"44238":30117,"44239":30114,"44240":30115,"44241":30328,"44242":30342,"44243":30343,"44244":30344,"44245":30408,"44246":30406,"44247":30403,"44248":30405,"44249":30465,"44250":30457,"44251":30456,"44252":30473,"44253":30475,"44254":30462,"44255":30460,"44256":30471,"44257":30684,"44258":30722,"44259":30740,"44260":30732,"44261":30733,"44262":31046,"44263":31049,"44264":31048,"44265":31047,"44266":31161,"44267":31162,"44268":31185,"44269":31186,"44270":31179,"44271":31359,"44272":31361,"44273":31487,"44274":31485,"44275":31869,"44276":32002,"44277":32005,"44278":32000,"44279":32009,"44280":32007,"44281":32004,"44282":32006,"44283":32568,"44284":32654,"44285":32703,"44286":32772,"44352":32784,"44353":32781,"44354":32785,"44355":32822,"44356":32982,"44357":32997,"44358":32986,"44359":32963,"44360":32964,"44361":32972,"44362":32993,"44363":32987,"44364":32974,"44365":32990,"44366":32996,"44367":32989,"44368":33268,"44369":33314,"44370":33511,"44371":33539,"44372":33541,"44373":33507,"44374":33499,"44375":33510,"44376":33540,"44377":33509,"44378":33538,"44379":33545,"44380":33490,"44381":33495,"44382":33521,"44383":33537,"44384":33500,"44385":33492,"44386":33489,"44387":33502,"44388":33491,"44389":33503,"44390":33519,"44391":33542,"44392":34384,"44393":34425,"44394":34427,"44395":34426,"44396":34893,"44397":34923,"44398":35201,"44399":35284,"44400":35336,"44401":35330,"44402":35331,"44403":35998,"44404":36000,"44405":36212,"44406":36211,"44407":36276,"44408":36557,"44409":36556,"44410":36848,"44411":36838,"44412":36834,"44413":36842,"44414":36837,"44449":36845,"44450":36843,"44451":36836,"44452":36840,"44453":37066,"44454":37070,"44455":37057,"44456":37059,"44457":37195,"44458":37194,"44459":37325,"44460":38274,"44461":38480,"44462":38475,"44463":38476,"44464":38477,"44465":38754,"44466":38761,"44467":38859,"44468":38893,"44469":38899,"44470":38913,"44471":39080,"44472":39131,"44473":39135,"44474":39318,"44475":39321,"44476":20056,"44477":20147,"44478":20492,"44479":20493,"44480":20515,"44481":20463,"44482":20518,"44483":20517,"44484":20472,"44485":20521,"44486":20502,"44487":20486,"44488":20540,"44489":20511,"44490":20506,"44491":20498,"44492":20497,"44493":20474,"44494":20480,"44495":20500,"44496":20520,"44497":20465,"44498":20513,"44499":20491,"44500":20505,"44501":20504,"44502":20467,"44503":20462,"44504":20525,"44505":20522,"44506":20478,"44507":20523,"44508":20489,"44509":20860,"44510":20900,"44511":20901,"44512":20898,"44513":20941,"44514":20940,"44515":20934,"44516":20939,"44517":21078,"44518":21084,"44519":21076,"44520":21083,"44521":21085,"44522":21290,"44523":21375,"44524":21407,"44525":21405,"44526":21471,"44527":21736,"44528":21776,"44529":21761,"44530":21815,"44531":21756,"44532":21733,"44533":21746,"44534":21766,"44535":21754,"44536":21780,"44537":21737,"44538":21741,"44539":21729,"44540":21769,"44541":21742,"44542":21738,"44608":21734,"44609":21799,"44610":21767,"44611":21757,"44612":21775,"44613":22275,"44614":22276,"44615":22466,"44616":22484,"44617":22475,"44618":22467,"44619":22537,"44620":22799,"44621":22871,"44622":22872,"44623":22874,"44624":23057,"44625":23064,"44626":23068,"44627":23071,"44628":23067,"44629":23059,"44630":23020,"44631":23072,"44632":23075,"44633":23081,"44634":23077,"44635":23052,"44636":23049,"44637":23403,"44638":23640,"44639":23472,"44640":23475,"44641":23478,"44642":23476,"44643":23470,"44644":23477,"44645":23481,"44646":23480,"44647":23556,"44648":23633,"44649":23637,"44650":23632,"44651":23789,"44652":23805,"44653":23803,"44654":23786,"44655":23784,"44656":23792,"44657":23798,"44658":23809,"44659":23796,"44660":24046,"44661":24109,"44662":24107,"44663":24235,"44664":24237,"44665":24231,"44666":24369,"44667":24466,"44668":24465,"44669":24464,"44670":24665,"44705":24675,"44706":24677,"44707":24656,"44708":24661,"44709":24685,"44710":24681,"44711":24687,"44712":24708,"44713":24735,"44714":24730,"44715":24717,"44716":24724,"44717":24716,"44718":24709,"44719":24726,"44720":25159,"44721":25331,"44722":25352,"44723":25343,"44724":25422,"44725":25406,"44726":25391,"44727":25429,"44728":25410,"44729":25414,"44730":25423,"44731":25417,"44732":25402,"44733":25424,"44734":25405,"44735":25386,"44736":25387,"44737":25384,"44738":25421,"44739":25420,"44740":25928,"44741":25929,"44742":26009,"44743":26049,"44744":26053,"44745":26178,"44746":26185,"44747":26191,"44748":26179,"44749":26194,"44750":26188,"44751":26181,"44752":26177,"44753":26360,"44754":26388,"44755":26389,"44756":26391,"44757":26657,"44758":26680,"44759":26696,"44760":26694,"44761":26707,"44762":26681,"44763":26690,"44764":26708,"44765":26665,"44766":26803,"44767":26647,"44768":26700,"44769":26705,"44770":26685,"44771":26612,"44772":26704,"44773":26688,"44774":26684,"44775":26691,"44776":26666,"44777":26693,"44778":26643,"44779":26648,"44780":26689,"44781":27530,"44782":27529,"44783":27575,"44784":27683,"44785":27687,"44786":27688,"44787":27686,"44788":27684,"44789":27888,"44790":28010,"44791":28053,"44792":28040,"44793":28039,"44794":28006,"44795":28024,"44796":28023,"44797":27993,"44798":28051,"44864":28012,"44865":28041,"44866":28014,"44867":27994,"44868":28020,"44869":28009,"44870":28044,"44871":28042,"44872":28025,"44873":28037,"44874":28005,"44875":28052,"44876":28874,"44877":28888,"44878":28900,"44879":28889,"44880":28872,"44881":28879,"44882":29241,"44883":29305,"44884":29436,"44885":29433,"44886":29437,"44887":29432,"44888":29431,"44889":29574,"44890":29677,"44891":29705,"44892":29678,"44893":29664,"44894":29674,"44895":29662,"44896":30036,"44897":30045,"44898":30044,"44899":30042,"44900":30041,"44901":30142,"44902":30149,"44903":30151,"44904":30130,"44905":30131,"44906":30141,"44907":30140,"44908":30137,"44909":30146,"44910":30136,"44911":30347,"44912":30384,"44913":30410,"44914":30413,"44915":30414,"44916":30505,"44917":30495,"44918":30496,"44919":30504,"44920":30697,"44921":30768,"44922":30759,"44923":30776,"44924":30749,"44925":30772,"44926":30775,"44961":30757,"44962":30765,"44963":30752,"44964":30751,"44965":30770,"44966":31061,"44967":31056,"44968":31072,"44969":31071,"44970":31062,"44971":31070,"44972":31069,"44973":31063,"44974":31066,"44975":31204,"44976":31203,"44977":31207,"44978":31199,"44979":31206,"44980":31209,"44981":31192,"44982":31364,"44983":31368,"44984":31449,"44985":31494,"44986":31505,"44987":31881,"44988":32033,"44989":32023,"44990":32011,"44991":32010,"44992":32032,"44993":32034,"44994":32020,"44995":32016,"44996":32021,"44997":32026,"44998":32028,"44999":32013,"45000":32025,"45001":32027,"45002":32570,"45003":32607,"45004":32660,"45005":32709,"45006":32705,"45007":32774,"45008":32792,"45009":32789,"45010":32793,"45011":32791,"45012":32829,"45013":32831,"45014":33009,"45015":33026,"45016":33008,"45017":33029,"45018":33005,"45019":33012,"45020":33030,"45021":33016,"45022":33011,"45023":33032,"45024":33021,"45025":33034,"45026":33020,"45027":33007,"45028":33261,"45029":33260,"45030":33280,"45031":33296,"45032":33322,"45033":33323,"45034":33320,"45035":33324,"45036":33467,"45037":33579,"45038":33618,"45039":33620,"45040":33610,"45041":33592,"45042":33616,"45043":33609,"45044":33589,"45045":33588,"45046":33615,"45047":33586,"45048":33593,"45049":33590,"45050":33559,"45051":33600,"45052":33585,"45053":33576,"45054":33603,"45120":34388,"45121":34442,"45122":34474,"45123":34451,"45124":34468,"45125":34473,"45126":34444,"45127":34467,"45128":34460,"45129":34928,"45130":34935,"45131":34945,"45132":34946,"45133":34941,"45134":34937,"45135":35352,"45136":35344,"45137":35342,"45138":35340,"45139":35349,"45140":35338,"45141":35351,"45142":35347,"45143":35350,"45144":35343,"45145":35345,"45146":35912,"45147":35962,"45148":35961,"45149":36001,"45150":36002,"45151":36215,"45152":36524,"45153":36562,"45154":36564,"45155":36559,"45156":36785,"45157":36865,"45158":36870,"45159":36855,"45160":36864,"45161":36858,"45162":36852,"45163":36867,"45164":36861,"45165":36869,"45166":36856,"45167":37013,"45168":37089,"45169":37085,"45170":37090,"45171":37202,"45172":37197,"45173":37196,"45174":37336,"45175":37341,"45176":37335,"45177":37340,"45178":37337,"45179":38275,"45180":38498,"45181":38499,"45182":38497,"45217":38491,"45218":38493,"45219":38500,"45220":38488,"45221":38494,"45222":38587,"45223":39138,"45224":39340,"45225":39592,"45226":39640,"45227":39717,"45228":39730,"45229":39740,"45230":20094,"45231":20602,"45232":20605,"45233":20572,"45234":20551,"45235":20547,"45236":20556,"45237":20570,"45238":20553,"45239":20581,"45240":20598,"45241":20558,"45242":20565,"45243":20597,"45244":20596,"45245":20599,"45246":20559,"45247":20495,"45248":20591,"45249":20589,"45250":20828,"45251":20885,"45252":20976,"45253":21098,"45254":21103,"45255":21202,"45256":21209,"45257":21208,"45258":21205,"45259":21264,"45260":21263,"45261":21273,"45262":21311,"45263":21312,"45264":21310,"45265":21443,"45266":26364,"45267":21830,"45268":21866,"45269":21862,"45270":21828,"45271":21854,"45272":21857,"45273":21827,"45274":21834,"45275":21809,"45276":21846,"45277":21839,"45278":21845,"45279":21807,"45280":21860,"45281":21816,"45282":21806,"45283":21852,"45284":21804,"45285":21859,"45286":21811,"45287":21825,"45288":21847,"45289":22280,"45290":22283,"45291":22281,"45292":22495,"45293":22533,"45294":22538,"45295":22534,"45296":22496,"45297":22500,"45298":22522,"45299":22530,"45300":22581,"45301":22519,"45302":22521,"45303":22816,"45304":22882,"45305":23094,"45306":23105,"45307":23113,"45308":23142,"45309":23146,"45310":23104,"45376":23100,"45377":23138,"45378":23130,"45379":23110,"45380":23114,"45381":23408,"45382":23495,"45383":23493,"45384":23492,"45385":23490,"45386":23487,"45387":23494,"45388":23561,"45389":23560,"45390":23559,"45391":23648,"45392":23644,"45393":23645,"45394":23815,"45395":23814,"45396":23822,"45397":23835,"45398":23830,"45399":23842,"45400":23825,"45401":23849,"45402":23828,"45403":23833,"45404":23844,"45405":23847,"45406":23831,"45407":24034,"45408":24120,"45409":24118,"45410":24115,"45411":24119,"45412":24247,"45413":24248,"45414":24246,"45415":24245,"45416":24254,"45417":24373,"45418":24375,"45419":24407,"45420":24428,"45421":24425,"45422":24427,"45423":24471,"45424":24473,"45425":24478,"45426":24472,"45427":24481,"45428":24480,"45429":24476,"45430":24703,"45431":24739,"45432":24713,"45433":24736,"45434":24744,"45435":24779,"45436":24756,"45437":24806,"45438":24765,"45473":24773,"45474":24763,"45475":24757,"45476":24796,"45477":24764,"45478":24792,"45479":24789,"45480":24774,"45481":24799,"45482":24760,"45483":24794,"45484":24775,"45485":25114,"45486":25115,"45487":25160,"45488":25504,"45489":25511,"45490":25458,"45491":25494,"45492":25506,"45493":25509,"45494":25463,"45495":25447,"45496":25496,"45497":25514,"45498":25457,"45499":25513,"45500":25481,"45501":25475,"45502":25499,"45503":25451,"45504":25512,"45505":25476,"45506":25480,"45507":25497,"45508":25505,"45509":25516,"45510":25490,"45511":25487,"45512":25472,"45513":25467,"45514":25449,"45515":25448,"45516":25466,"45517":25949,"45518":25942,"45519":25937,"45520":25945,"45521":25943,"45522":21855,"45523":25935,"45524":25944,"45525":25941,"45526":25940,"45527":26012,"45528":26011,"45529":26028,"45530":26063,"45531":26059,"45532":26060,"45533":26062,"45534":26205,"45535":26202,"45536":26212,"45537":26216,"45538":26214,"45539":26206,"45540":26361,"45541":21207,"45542":26395,"45543":26753,"45544":26799,"45545":26786,"45546":26771,"45547":26805,"45548":26751,"45549":26742,"45550":26801,"45551":26791,"45552":26775,"45553":26800,"45554":26755,"45555":26820,"45556":26797,"45557":26758,"45558":26757,"45559":26772,"45560":26781,"45561":26792,"45562":26783,"45563":26785,"45564":26754,"45565":27442,"45566":27578,"45632":27627,"45633":27628,"45634":27691,"45635":28046,"45636":28092,"45637":28147,"45638":28121,"45639":28082,"45640":28129,"45641":28108,"45642":28132,"45643":28155,"45644":28154,"45645":28165,"45646":28103,"45647":28107,"45648":28079,"45649":28113,"45650":28078,"45651":28126,"45652":28153,"45653":28088,"45654":28151,"45655":28149,"45656":28101,"45657":28114,"45658":28186,"45659":28085,"45660":28122,"45661":28139,"45662":28120,"45663":28138,"45664":28145,"45665":28142,"45666":28136,"45667":28102,"45668":28100,"45669":28074,"45670":28140,"45671":28095,"45672":28134,"45673":28921,"45674":28937,"45675":28938,"45676":28925,"45677":28911,"45678":29245,"45679":29309,"45680":29313,"45681":29468,"45682":29467,"45683":29462,"45684":29459,"45685":29465,"45686":29575,"45687":29701,"45688":29706,"45689":29699,"45690":29702,"45691":29694,"45692":29709,"45693":29920,"45694":29942,"45729":29943,"45730":29980,"45731":29986,"45732":30053,"45733":30054,"45734":30050,"45735":30064,"45736":30095,"45737":30164,"45738":30165,"45739":30133,"45740":30154,"45741":30157,"45742":30350,"45743":30420,"45744":30418,"45745":30427,"45746":30519,"45747":30526,"45748":30524,"45749":30518,"45750":30520,"45751":30522,"45752":30827,"45753":30787,"45754":30798,"45755":31077,"45756":31080,"45757":31085,"45758":31227,"45759":31378,"45760":31381,"45761":31520,"45762":31528,"45763":31515,"45764":31532,"45765":31526,"45766":31513,"45767":31518,"45768":31534,"45769":31890,"45770":31895,"45771":31893,"45772":32070,"45773":32067,"45774":32113,"45775":32046,"45776":32057,"45777":32060,"45778":32064,"45779":32048,"45780":32051,"45781":32068,"45782":32047,"45783":32066,"45784":32050,"45785":32049,"45786":32573,"45787":32670,"45788":32666,"45789":32716,"45790":32718,"45791":32722,"45792":32796,"45793":32842,"45794":32838,"45795":33071,"45796":33046,"45797":33059,"45798":33067,"45799":33065,"45800":33072,"45801":33060,"45802":33282,"45803":33333,"45804":33335,"45805":33334,"45806":33337,"45807":33678,"45808":33694,"45809":33688,"45810":33656,"45811":33698,"45812":33686,"45813":33725,"45814":33707,"45815":33682,"45816":33674,"45817":33683,"45818":33673,"45819":33696,"45820":33655,"45821":33659,"45822":33660,"45888":33670,"45889":33703,"45890":34389,"45891":24426,"45892":34503,"45893":34496,"45894":34486,"45895":34500,"45896":34485,"45897":34502,"45898":34507,"45899":34481,"45900":34479,"45901":34505,"45902":34899,"45903":34974,"45904":34952,"45905":34987,"45906":34962,"45907":34966,"45908":34957,"45909":34955,"45910":35219,"45911":35215,"45912":35370,"45913":35357,"45914":35363,"45915":35365,"45916":35377,"45917":35373,"45918":35359,"45919":35355,"45920":35362,"45921":35913,"45922":35930,"45923":36009,"45924":36012,"45925":36011,"45926":36008,"45927":36010,"45928":36007,"45929":36199,"45930":36198,"45931":36286,"45932":36282,"45933":36571,"45934":36575,"45935":36889,"45936":36877,"45937":36890,"45938":36887,"45939":36899,"45940":36895,"45941":36893,"45942":36880,"45943":36885,"45944":36894,"45945":36896,"45946":36879,"45947":36898,"45948":36886,"45949":36891,"45950":36884,"45985":37096,"45986":37101,"45987":37117,"45988":37207,"45989":37326,"45990":37365,"45991":37350,"45992":37347,"45993":37351,"45994":37357,"45995":37353,"45996":38281,"45997":38506,"45998":38517,"45999":38515,"46000":38520,"46001":38512,"46002":38516,"46003":38518,"46004":38519,"46005":38508,"46006":38592,"46007":38634,"46008":38633,"46009":31456,"46010":31455,"46011":38914,"46012":38915,"46013":39770,"46014":40165,"46015":40565,"46016":40575,"46017":40613,"46018":40635,"46019":20642,"46020":20621,"46021":20613,"46022":20633,"46023":20625,"46024":20608,"46025":20630,"46026":20632,"46027":20634,"46028":26368,"46029":20977,"46030":21106,"46031":21108,"46032":21109,"46033":21097,"46034":21214,"46035":21213,"46036":21211,"46037":21338,"46038":21413,"46039":21883,"46040":21888,"46041":21927,"46042":21884,"46043":21898,"46044":21917,"46045":21912,"46046":21890,"46047":21916,"46048":21930,"46049":21908,"46050":21895,"46051":21899,"46052":21891,"46053":21939,"46054":21934,"46055":21919,"46056":21822,"46057":21938,"46058":21914,"46059":21947,"46060":21932,"46061":21937,"46062":21886,"46063":21897,"46064":21931,"46065":21913,"46066":22285,"46067":22575,"46068":22570,"46069":22580,"46070":22564,"46071":22576,"46072":22577,"46073":22561,"46074":22557,"46075":22560,"46076":22777,"46077":22778,"46078":22880,"46144":23159,"46145":23194,"46146":23167,"46147":23186,"46148":23195,"46149":23207,"46150":23411,"46151":23409,"46152":23506,"46153":23500,"46154":23507,"46155":23504,"46156":23562,"46157":23563,"46158":23601,"46159":23884,"46160":23888,"46161":23860,"46162":23879,"46163":24061,"46164":24133,"46165":24125,"46166":24128,"46167":24131,"46168":24190,"46169":24266,"46170":24257,"46171":24258,"46172":24260,"46173":24380,"46174":24429,"46175":24489,"46176":24490,"46177":24488,"46178":24785,"46179":24801,"46180":24754,"46181":24758,"46182":24800,"46183":24860,"46184":24867,"46185":24826,"46186":24853,"46187":24816,"46188":24827,"46189":24820,"46190":24936,"46191":24817,"46192":24846,"46193":24822,"46194":24841,"46195":24832,"46196":24850,"46197":25119,"46198":25161,"46199":25507,"46200":25484,"46201":25551,"46202":25536,"46203":25577,"46204":25545,"46205":25542,"46206":25549,"46241":25554,"46242":25571,"46243":25552,"46244":25569,"46245":25558,"46246":25581,"46247":25582,"46248":25462,"46249":25588,"46250":25578,"46251":25563,"46252":25682,"46253":25562,"46254":25593,"46255":25950,"46256":25958,"46257":25954,"46258":25955,"46259":26001,"46260":26000,"46261":26031,"46262":26222,"46263":26224,"46264":26228,"46265":26230,"46266":26223,"46267":26257,"46268":26234,"46269":26238,"46270":26231,"46271":26366,"46272":26367,"46273":26399,"46274":26397,"46275":26874,"46276":26837,"46277":26848,"46278":26840,"46279":26839,"46280":26885,"46281":26847,"46282":26869,"46283":26862,"46284":26855,"46285":26873,"46286":26834,"46287":26866,"46288":26851,"46289":26827,"46290":26829,"46291":26893,"46292":26898,"46293":26894,"46294":26825,"46295":26842,"46296":26990,"46297":26875,"46298":27454,"46299":27450,"46300":27453,"46301":27544,"46302":27542,"46303":27580,"46304":27631,"46305":27694,"46306":27695,"46307":27692,"46308":28207,"46309":28216,"46310":28244,"46311":28193,"46312":28210,"46313":28263,"46314":28234,"46315":28192,"46316":28197,"46317":28195,"46318":28187,"46319":28251,"46320":28248,"46321":28196,"46322":28246,"46323":28270,"46324":28205,"46325":28198,"46326":28271,"46327":28212,"46328":28237,"46329":28218,"46330":28204,"46331":28227,"46332":28189,"46333":28222,"46334":28363,"46400":28297,"46401":28185,"46402":28238,"46403":28259,"46404":28228,"46405":28274,"46406":28265,"46407":28255,"46408":28953,"46409":28954,"46410":28966,"46411":28976,"46412":28961,"46413":28982,"46414":29038,"46415":28956,"46416":29260,"46417":29316,"46418":29312,"46419":29494,"46420":29477,"46421":29492,"46422":29481,"46423":29754,"46424":29738,"46425":29747,"46426":29730,"46427":29733,"46428":29749,"46429":29750,"46430":29748,"46431":29743,"46432":29723,"46433":29734,"46434":29736,"46435":29989,"46436":29990,"46437":30059,"46438":30058,"46439":30178,"46440":30171,"46441":30179,"46442":30169,"46443":30168,"46444":30174,"46445":30176,"46446":30331,"46447":30332,"46448":30358,"46449":30355,"46450":30388,"46451":30428,"46452":30543,"46453":30701,"46454":30813,"46455":30828,"46456":30831,"46457":31245,"46458":31240,"46459":31243,"46460":31237,"46461":31232,"46462":31384,"46497":31383,"46498":31382,"46499":31461,"46500":31459,"46501":31561,"46502":31574,"46503":31558,"46504":31568,"46505":31570,"46506":31572,"46507":31565,"46508":31563,"46509":31567,"46510":31569,"46511":31903,"46512":31909,"46513":32094,"46514":32080,"46515":32104,"46516":32085,"46517":32043,"46518":32110,"46519":32114,"46520":32097,"46521":32102,"46522":32098,"46523":32112,"46524":32115,"46525":21892,"46526":32724,"46527":32725,"46528":32779,"46529":32850,"46530":32901,"46531":33109,"46532":33108,"46533":33099,"46534":33105,"46535":33102,"46536":33081,"46537":33094,"46538":33086,"46539":33100,"46540":33107,"46541":33140,"46542":33298,"46543":33308,"46544":33769,"46545":33795,"46546":33784,"46547":33805,"46548":33760,"46549":33733,"46550":33803,"46551":33729,"46552":33775,"46553":33777,"46554":33780,"46555":33879,"46556":33802,"46557":33776,"46558":33804,"46559":33740,"46560":33789,"46561":33778,"46562":33738,"46563":33848,"46564":33806,"46565":33796,"46566":33756,"46567":33799,"46568":33748,"46569":33759,"46570":34395,"46571":34527,"46572":34521,"46573":34541,"46574":34516,"46575":34523,"46576":34532,"46577":34512,"46578":34526,"46579":34903,"46580":35009,"46581":35010,"46582":34993,"46583":35203,"46584":35222,"46585":35387,"46586":35424,"46587":35413,"46588":35422,"46589":35388,"46590":35393,"46656":35412,"46657":35419,"46658":35408,"46659":35398,"46660":35380,"46661":35386,"46662":35382,"46663":35414,"46664":35937,"46665":35970,"46666":36015,"46667":36028,"46668":36019,"46669":36029,"46670":36033,"46671":36027,"46672":36032,"46673":36020,"46674":36023,"46675":36022,"46676":36031,"46677":36024,"46678":36234,"46679":36229,"46680":36225,"46681":36302,"46682":36317,"46683":36299,"46684":36314,"46685":36305,"46686":36300,"46687":36315,"46688":36294,"46689":36603,"46690":36600,"46691":36604,"46692":36764,"46693":36910,"46694":36917,"46695":36913,"46696":36920,"46697":36914,"46698":36918,"46699":37122,"46700":37109,"46701":37129,"46702":37118,"46703":37219,"46704":37221,"46705":37327,"46706":37396,"46707":37397,"46708":37411,"46709":37385,"46710":37406,"46711":37389,"46712":37392,"46713":37383,"46714":37393,"46715":38292,"46716":38287,"46717":38283,"46718":38289,"46753":38291,"46754":38290,"46755":38286,"46756":38538,"46757":38542,"46758":38539,"46759":38525,"46760":38533,"46761":38534,"46762":38541,"46763":38514,"46764":38532,"46765":38593,"46766":38597,"46767":38596,"46768":38598,"46769":38599,"46770":38639,"46771":38642,"46772":38860,"46773":38917,"46774":38918,"46775":38920,"46776":39143,"46777":39146,"46778":39151,"46779":39145,"46780":39154,"46781":39149,"46782":39342,"46783":39341,"46784":40643,"46785":40653,"46786":40657,"46787":20098,"46788":20653,"46789":20661,"46790":20658,"46791":20659,"46792":20677,"46793":20670,"46794":20652,"46795":20663,"46796":20667,"46797":20655,"46798":20679,"46799":21119,"46800":21111,"46801":21117,"46802":21215,"46803":21222,"46804":21220,"46805":21218,"46806":21219,"46807":21295,"46808":21983,"46809":21992,"46810":21971,"46811":21990,"46812":21966,"46813":21980,"46814":21959,"46815":21969,"46816":21987,"46817":21988,"46818":21999,"46819":21978,"46820":21985,"46821":21957,"46822":21958,"46823":21989,"46824":21961,"46825":22290,"46826":22291,"46827":22622,"46828":22609,"46829":22616,"46830":22615,"46831":22618,"46832":22612,"46833":22635,"46834":22604,"46835":22637,"46836":22602,"46837":22626,"46838":22610,"46839":22603,"46840":22887,"46841":23233,"46842":23241,"46843":23244,"46844":23230,"46845":23229,"46846":23228,"46912":23219,"46913":23234,"46914":23218,"46915":23913,"46916":23919,"46917":24140,"46918":24185,"46919":24265,"46920":24264,"46921":24338,"46922":24409,"46923":24492,"46924":24494,"46925":24858,"46926":24847,"46927":24904,"46928":24863,"46929":24819,"46930":24859,"46931":24825,"46932":24833,"46933":24840,"46934":24910,"46935":24908,"46936":24900,"46937":24909,"46938":24894,"46939":24884,"46940":24871,"46941":24845,"46942":24838,"46943":24887,"46944":25121,"46945":25122,"46946":25619,"46947":25662,"46948":25630,"46949":25642,"46950":25645,"46951":25661,"46952":25644,"46953":25615,"46954":25628,"46955":25620,"46956":25613,"46957":25654,"46958":25622,"46959":25623,"46960":25606,"46961":25964,"46962":26015,"46963":26032,"46964":26263,"46965":26249,"46966":26247,"46967":26248,"46968":26262,"46969":26244,"46970":26264,"46971":26253,"46972":26371,"46973":27028,"46974":26989,"47009":26970,"47010":26999,"47011":26976,"47012":26964,"47013":26997,"47014":26928,"47015":27010,"47016":26954,"47017":26984,"47018":26987,"47019":26974,"47020":26963,"47021":27001,"47022":27014,"47023":26973,"47024":26979,"47025":26971,"47026":27463,"47027":27506,"47028":27584,"47029":27583,"47030":27603,"47031":27645,"47032":28322,"47033":28335,"47034":28371,"47035":28342,"47036":28354,"47037":28304,"47038":28317,"47039":28359,"47040":28357,"47041":28325,"47042":28312,"47043":28348,"47044":28346,"47045":28331,"47046":28369,"47047":28310,"47048":28316,"47049":28356,"47050":28372,"47051":28330,"47052":28327,"47053":28340,"47054":29006,"47055":29017,"47056":29033,"47057":29028,"47058":29001,"47059":29031,"47060":29020,"47061":29036,"47062":29030,"47063":29004,"47064":29029,"47065":29022,"47066":28998,"47067":29032,"47068":29014,"47069":29242,"47070":29266,"47071":29495,"47072":29509,"47073":29503,"47074":29502,"47075":29807,"47076":29786,"47077":29781,"47078":29791,"47079":29790,"47080":29761,"47081":29759,"47082":29785,"47083":29787,"47084":29788,"47085":30070,"47086":30072,"47087":30208,"47088":30192,"47089":30209,"47090":30194,"47091":30193,"47092":30202,"47093":30207,"47094":30196,"47095":30195,"47096":30430,"47097":30431,"47098":30555,"47099":30571,"47100":30566,"47101":30558,"47102":30563,"47168":30585,"47169":30570,"47170":30572,"47171":30556,"47172":30565,"47173":30568,"47174":30562,"47175":30702,"47176":30862,"47177":30896,"47178":30871,"47179":30872,"47180":30860,"47181":30857,"47182":30844,"47183":30865,"47184":30867,"47185":30847,"47186":31098,"47187":31103,"47188":31105,"47189":33836,"47190":31165,"47191":31260,"47192":31258,"47193":31264,"47194":31252,"47195":31263,"47196":31262,"47197":31391,"47198":31392,"47199":31607,"47200":31680,"47201":31584,"47202":31598,"47203":31591,"47204":31921,"47205":31923,"47206":31925,"47207":32147,"47208":32121,"47209":32145,"47210":32129,"47211":32143,"47212":32091,"47213":32622,"47214":32617,"47215":32618,"47216":32626,"47217":32681,"47218":32680,"47219":32676,"47220":32854,"47221":32856,"47222":32902,"47223":32900,"47224":33137,"47225":33136,"47226":33144,"47227":33125,"47228":33134,"47229":33139,"47230":33131,"47265":33145,"47266":33146,"47267":33126,"47268":33285,"47269":33351,"47270":33922,"47271":33911,"47272":33853,"47273":33841,"47274":33909,"47275":33894,"47276":33899,"47277":33865,"47278":33900,"47279":33883,"47280":33852,"47281":33845,"47282":33889,"47283":33891,"47284":33897,"47285":33901,"47286":33862,"47287":34398,"47288":34396,"47289":34399,"47290":34553,"47291":34579,"47292":34568,"47293":34567,"47294":34560,"47295":34558,"47296":34555,"47297":34562,"47298":34563,"47299":34566,"47300":34570,"47301":34905,"47302":35039,"47303":35028,"47304":35033,"47305":35036,"47306":35032,"47307":35037,"47308":35041,"47309":35018,"47310":35029,"47311":35026,"47312":35228,"47313":35299,"47314":35435,"47315":35442,"47316":35443,"47317":35430,"47318":35433,"47319":35440,"47320":35463,"47321":35452,"47322":35427,"47323":35488,"47324":35441,"47325":35461,"47326":35437,"47327":35426,"47328":35438,"47329":35436,"47330":35449,"47331":35451,"47332":35390,"47333":35432,"47334":35938,"47335":35978,"47336":35977,"47337":36042,"47338":36039,"47339":36040,"47340":36036,"47341":36018,"47342":36035,"47343":36034,"47344":36037,"47345":36321,"47346":36319,"47347":36328,"47348":36335,"47349":36339,"47350":36346,"47351":36330,"47352":36324,"47353":36326,"47354":36530,"47355":36611,"47356":36617,"47357":36606,"47358":36618,"47424":36767,"47425":36786,"47426":36939,"47427":36938,"47428":36947,"47429":36930,"47430":36948,"47431":36924,"47432":36949,"47433":36944,"47434":36935,"47435":36943,"47436":36942,"47437":36941,"47438":36945,"47439":36926,"47440":36929,"47441":37138,"47442":37143,"47443":37228,"47444":37226,"47445":37225,"47446":37321,"47447":37431,"47448":37463,"47449":37432,"47450":37437,"47451":37440,"47452":37438,"47453":37467,"47454":37451,"47455":37476,"47456":37457,"47457":37428,"47458":37449,"47459":37453,"47460":37445,"47461":37433,"47462":37439,"47463":37466,"47464":38296,"47465":38552,"47466":38548,"47467":38549,"47468":38605,"47469":38603,"47470":38601,"47471":38602,"47472":38647,"47473":38651,"47474":38649,"47475":38646,"47476":38742,"47477":38772,"47478":38774,"47479":38928,"47480":38929,"47481":38931,"47482":38922,"47483":38930,"47484":38924,"47485":39164,"47486":39156,"47521":39165,"47522":39166,"47523":39347,"47524":39345,"47525":39348,"47526":39649,"47527":40169,"47528":40578,"47529":40718,"47530":40723,"47531":40736,"47532":20711,"47533":20718,"47534":20709,"47535":20694,"47536":20717,"47537":20698,"47538":20693,"47539":20687,"47540":20689,"47541":20721,"47542":20686,"47543":20713,"47544":20834,"47545":20979,"47546":21123,"47547":21122,"47548":21297,"47549":21421,"47550":22014,"47551":22016,"47552":22043,"47553":22039,"47554":22013,"47555":22036,"47556":22022,"47557":22025,"47558":22029,"47559":22030,"47560":22007,"47561":22038,"47562":22047,"47563":22024,"47564":22032,"47565":22006,"47566":22296,"47567":22294,"47568":22645,"47569":22654,"47570":22659,"47571":22675,"47572":22666,"47573":22649,"47574":22661,"47575":22653,"47576":22781,"47577":22821,"47578":22818,"47579":22820,"47580":22890,"47581":22889,"47582":23265,"47583":23270,"47584":23273,"47585":23255,"47586":23254,"47587":23256,"47588":23267,"47589":23413,"47590":23518,"47591":23527,"47592":23521,"47593":23525,"47594":23526,"47595":23528,"47596":23522,"47597":23524,"47598":23519,"47599":23565,"47600":23650,"47601":23940,"47602":23943,"47603":24155,"47604":24163,"47605":24149,"47606":24151,"47607":24148,"47608":24275,"47609":24278,"47610":24330,"47611":24390,"47612":24432,"47613":24505,"47614":24903,"47680":24895,"47681":24907,"47682":24951,"47683":24930,"47684":24931,"47685":24927,"47686":24922,"47687":24920,"47688":24949,"47689":25130,"47690":25735,"47691":25688,"47692":25684,"47693":25764,"47694":25720,"47695":25695,"47696":25722,"47697":25681,"47698":25703,"47699":25652,"47700":25709,"47701":25723,"47702":25970,"47703":26017,"47704":26071,"47705":26070,"47706":26274,"47707":26280,"47708":26269,"47709":27036,"47710":27048,"47711":27029,"47712":27073,"47713":27054,"47714":27091,"47715":27083,"47716":27035,"47717":27063,"47718":27067,"47719":27051,"47720":27060,"47721":27088,"47722":27085,"47723":27053,"47724":27084,"47725":27046,"47726":27075,"47727":27043,"47728":27465,"47729":27468,"47730":27699,"47731":28467,"47732":28436,"47733":28414,"47734":28435,"47735":28404,"47736":28457,"47737":28478,"47738":28448,"47739":28460,"47740":28431,"47741":28418,"47742":28450,"47777":28415,"47778":28399,"47779":28422,"47780":28465,"47781":28472,"47782":28466,"47783":28451,"47784":28437,"47785":28459,"47786":28463,"47787":28552,"47788":28458,"47789":28396,"47790":28417,"47791":28402,"47792":28364,"47793":28407,"47794":29076,"47795":29081,"47796":29053,"47797":29066,"47798":29060,"47799":29074,"47800":29246,"47801":29330,"47802":29334,"47803":29508,"47804":29520,"47805":29796,"47806":29795,"47807":29802,"47808":29808,"47809":29805,"47810":29956,"47811":30097,"47812":30247,"47813":30221,"47814":30219,"47815":30217,"47816":30227,"47817":30433,"47818":30435,"47819":30596,"47820":30589,"47821":30591,"47822":30561,"47823":30913,"47824":30879,"47825":30887,"47826":30899,"47827":30889,"47828":30883,"47829":31118,"47830":31119,"47831":31117,"47832":31278,"47833":31281,"47834":31402,"47835":31401,"47836":31469,"47837":31471,"47838":31649,"47839":31637,"47840":31627,"47841":31605,"47842":31639,"47843":31645,"47844":31636,"47845":31631,"47846":31672,"47847":31623,"47848":31620,"47849":31929,"47850":31933,"47851":31934,"47852":32187,"47853":32176,"47854":32156,"47855":32189,"47856":32190,"47857":32160,"47858":32202,"47859":32180,"47860":32178,"47861":32177,"47862":32186,"47863":32162,"47864":32191,"47865":32181,"47866":32184,"47867":32173,"47868":32210,"47869":32199,"47870":32172,"47936":32624,"47937":32736,"47938":32737,"47939":32735,"47940":32862,"47941":32858,"47942":32903,"47943":33104,"47944":33152,"47945":33167,"47946":33160,"47947":33162,"47948":33151,"47949":33154,"47950":33255,"47951":33274,"47952":33287,"47953":33300,"47954":33310,"47955":33355,"47956":33993,"47957":33983,"47958":33990,"47959":33988,"47960":33945,"47961":33950,"47962":33970,"47963":33948,"47964":33995,"47965":33976,"47966":33984,"47967":34003,"47968":33936,"47969":33980,"47970":34001,"47971":33994,"47972":34623,"47973":34588,"47974":34619,"47975":34594,"47976":34597,"47977":34612,"47978":34584,"47979":34645,"47980":34615,"47981":34601,"47982":35059,"47983":35074,"47984":35060,"47985":35065,"47986":35064,"47987":35069,"47988":35048,"47989":35098,"47990":35055,"47991":35494,"47992":35468,"47993":35486,"47994":35491,"47995":35469,"47996":35489,"47997":35475,"47998":35492,"48033":35498,"48034":35493,"48035":35496,"48036":35480,"48037":35473,"48038":35482,"48039":35495,"48040":35946,"48041":35981,"48042":35980,"48043":36051,"48044":36049,"48045":36050,"48046":36203,"48047":36249,"48048":36245,"48049":36348,"48050":36628,"48051":36626,"48052":36629,"48053":36627,"48054":36771,"48055":36960,"48056":36952,"48057":36956,"48058":36963,"48059":36953,"48060":36958,"48061":36962,"48062":36957,"48063":36955,"48064":37145,"48065":37144,"48066":37150,"48067":37237,"48068":37240,"48069":37239,"48070":37236,"48071":37496,"48072":37504,"48073":37509,"48074":37528,"48075":37526,"48076":37499,"48077":37523,"48078":37532,"48079":37544,"48080":37500,"48081":37521,"48082":38305,"48083":38312,"48084":38313,"48085":38307,"48086":38309,"48087":38308,"48088":38553,"48089":38556,"48090":38555,"48091":38604,"48092":38610,"48093":38656,"48094":38780,"48095":38789,"48096":38902,"48097":38935,"48098":38936,"48099":39087,"48100":39089,"48101":39171,"48102":39173,"48103":39180,"48104":39177,"48105":39361,"48106":39599,"48107":39600,"48108":39654,"48109":39745,"48110":39746,"48111":40180,"48112":40182,"48113":40179,"48114":40636,"48115":40763,"48116":40778,"48117":20740,"48118":20736,"48119":20731,"48120":20725,"48121":20729,"48122":20738,"48123":20744,"48124":20745,"48125":20741,"48126":20956,"48192":21127,"48193":21128,"48194":21129,"48195":21133,"48196":21130,"48197":21232,"48198":21426,"48199":22062,"48200":22075,"48201":22073,"48202":22066,"48203":22079,"48204":22068,"48205":22057,"48206":22099,"48207":22094,"48208":22103,"48209":22132,"48210":22070,"48211":22063,"48212":22064,"48213":22656,"48214":22687,"48215":22686,"48216":22707,"48217":22684,"48218":22702,"48219":22697,"48220":22694,"48221":22893,"48222":23305,"48223":23291,"48224":23307,"48225":23285,"48226":23308,"48227":23304,"48228":23534,"48229":23532,"48230":23529,"48231":23531,"48232":23652,"48233":23653,"48234":23965,"48235":23956,"48236":24162,"48237":24159,"48238":24161,"48239":24290,"48240":24282,"48241":24287,"48242":24285,"48243":24291,"48244":24288,"48245":24392,"48246":24433,"48247":24503,"48248":24501,"48249":24950,"48250":24935,"48251":24942,"48252":24925,"48253":24917,"48254":24962,"48289":24956,"48290":24944,"48291":24939,"48292":24958,"48293":24999,"48294":24976,"48295":25003,"48296":24974,"48297":25004,"48298":24986,"48299":24996,"48300":24980,"48301":25006,"48302":25134,"48303":25705,"48304":25711,"48305":25721,"48306":25758,"48307":25778,"48308":25736,"48309":25744,"48310":25776,"48311":25765,"48312":25747,"48313":25749,"48314":25769,"48315":25746,"48316":25774,"48317":25773,"48318":25771,"48319":25754,"48320":25772,"48321":25753,"48322":25762,"48323":25779,"48324":25973,"48325":25975,"48326":25976,"48327":26286,"48328":26283,"48329":26292,"48330":26289,"48331":27171,"48332":27167,"48333":27112,"48334":27137,"48335":27166,"48336":27161,"48337":27133,"48338":27169,"48339":27155,"48340":27146,"48341":27123,"48342":27138,"48343":27141,"48344":27117,"48345":27153,"48346":27472,"48347":27470,"48348":27556,"48349":27589,"48350":27590,"48351":28479,"48352":28540,"48353":28548,"48354":28497,"48355":28518,"48356":28500,"48357":28550,"48358":28525,"48359":28507,"48360":28536,"48361":28526,"48362":28558,"48363":28538,"48364":28528,"48365":28516,"48366":28567,"48367":28504,"48368":28373,"48369":28527,"48370":28512,"48371":28511,"48372":29087,"48373":29100,"48374":29105,"48375":29096,"48376":29270,"48377":29339,"48378":29518,"48379":29527,"48380":29801,"48381":29835,"48382":29827,"48448":29822,"48449":29824,"48450":30079,"48451":30240,"48452":30249,"48453":30239,"48454":30244,"48455":30246,"48456":30241,"48457":30242,"48458":30362,"48459":30394,"48460":30436,"48461":30606,"48462":30599,"48463":30604,"48464":30609,"48465":30603,"48466":30923,"48467":30917,"48468":30906,"48469":30922,"48470":30910,"48471":30933,"48472":30908,"48473":30928,"48474":31295,"48475":31292,"48476":31296,"48477":31293,"48478":31287,"48479":31291,"48480":31407,"48481":31406,"48482":31661,"48483":31665,"48484":31684,"48485":31668,"48486":31686,"48487":31687,"48488":31681,"48489":31648,"48490":31692,"48491":31946,"48492":32224,"48493":32244,"48494":32239,"48495":32251,"48496":32216,"48497":32236,"48498":32221,"48499":32232,"48500":32227,"48501":32218,"48502":32222,"48503":32233,"48504":32158,"48505":32217,"48506":32242,"48507":32249,"48508":32629,"48509":32631,"48510":32687,"48545":32745,"48546":32806,"48547":33179,"48548":33180,"48549":33181,"48550":33184,"48551":33178,"48552":33176,"48553":34071,"48554":34109,"48555":34074,"48556":34030,"48557":34092,"48558":34093,"48559":34067,"48560":34065,"48561":34083,"48562":34081,"48563":34068,"48564":34028,"48565":34085,"48566":34047,"48567":34054,"48568":34690,"48569":34676,"48570":34678,"48571":34656,"48572":34662,"48573":34680,"48574":34664,"48575":34649,"48576":34647,"48577":34636,"48578":34643,"48579":34907,"48580":34909,"48581":35088,"48582":35079,"48583":35090,"48584":35091,"48585":35093,"48586":35082,"48587":35516,"48588":35538,"48589":35527,"48590":35524,"48591":35477,"48592":35531,"48593":35576,"48594":35506,"48595":35529,"48596":35522,"48597":35519,"48598":35504,"48599":35542,"48600":35533,"48601":35510,"48602":35513,"48603":35547,"48604":35916,"48605":35918,"48606":35948,"48607":36064,"48608":36062,"48609":36070,"48610":36068,"48611":36076,"48612":36077,"48613":36066,"48614":36067,"48615":36060,"48616":36074,"48617":36065,"48618":36205,"48619":36255,"48620":36259,"48621":36395,"48622":36368,"48623":36381,"48624":36386,"48625":36367,"48626":36393,"48627":36383,"48628":36385,"48629":36382,"48630":36538,"48631":36637,"48632":36635,"48633":36639,"48634":36649,"48635":36646,"48636":36650,"48637":36636,"48638":36638,"48704":36645,"48705":36969,"48706":36974,"48707":36968,"48708":36973,"48709":36983,"48710":37168,"48711":37165,"48712":37159,"48713":37169,"48714":37255,"48715":37257,"48716":37259,"48717":37251,"48718":37573,"48719":37563,"48720":37559,"48721":37610,"48722":37548,"48723":37604,"48724":37569,"48725":37555,"48726":37564,"48727":37586,"48728":37575,"48729":37616,"48730":37554,"48731":38317,"48732":38321,"48733":38660,"48734":38662,"48735":38663,"48736":38665,"48737":38752,"48738":38797,"48739":38795,"48740":38799,"48741":38945,"48742":38955,"48743":38940,"48744":39091,"48745":39178,"48746":39187,"48747":39186,"48748":39192,"48749":39389,"48750":39376,"48751":39391,"48752":39387,"48753":39377,"48754":39381,"48755":39378,"48756":39385,"48757":39607,"48758":39662,"48759":39663,"48760":39719,"48761":39749,"48762":39748,"48763":39799,"48764":39791,"48765":40198,"48766":40201,"48801":40195,"48802":40617,"48803":40638,"48804":40654,"48805":22696,"48806":40786,"48807":20754,"48808":20760,"48809":20756,"48810":20752,"48811":20757,"48812":20864,"48813":20906,"48814":20957,"48815":21137,"48816":21139,"48817":21235,"48818":22105,"48819":22123,"48820":22137,"48821":22121,"48822":22116,"48823":22136,"48824":22122,"48825":22120,"48826":22117,"48827":22129,"48828":22127,"48829":22124,"48830":22114,"48831":22134,"48832":22721,"48833":22718,"48834":22727,"48835":22725,"48836":22894,"48837":23325,"48838":23348,"48839":23416,"48840":23536,"48841":23566,"48842":24394,"48843":25010,"48844":24977,"48845":25001,"48846":24970,"48847":25037,"48848":25014,"48849":25022,"48850":25034,"48851":25032,"48852":25136,"48853":25797,"48854":25793,"48855":25803,"48856":25787,"48857":25788,"48858":25818,"48859":25796,"48860":25799,"48861":25794,"48862":25805,"48863":25791,"48864":25810,"48865":25812,"48866":25790,"48867":25972,"48868":26310,"48869":26313,"48870":26297,"48871":26308,"48872":26311,"48873":26296,"48874":27197,"48875":27192,"48876":27194,"48877":27225,"48878":27243,"48879":27224,"48880":27193,"48881":27204,"48882":27234,"48883":27233,"48884":27211,"48885":27207,"48886":27189,"48887":27231,"48888":27208,"48889":27481,"48890":27511,"48891":27653,"48892":28610,"48893":28593,"48894":28577,"48960":28611,"48961":28580,"48962":28609,"48963":28583,"48964":28595,"48965":28608,"48966":28601,"48967":28598,"48968":28582,"48969":28576,"48970":28596,"48971":29118,"48972":29129,"48973":29136,"48974":29138,"48975":29128,"48976":29141,"48977":29113,"48978":29134,"48979":29145,"48980":29148,"48981":29123,"48982":29124,"48983":29544,"48984":29852,"48985":29859,"48986":29848,"48987":29855,"48988":29854,"48989":29922,"48990":29964,"48991":29965,"48992":30260,"48993":30264,"48994":30266,"48995":30439,"48996":30437,"48997":30624,"48998":30622,"48999":30623,"49000":30629,"49001":30952,"49002":30938,"49003":30956,"49004":30951,"49005":31142,"49006":31309,"49007":31310,"49008":31302,"49009":31308,"49010":31307,"49011":31418,"49012":31705,"49013":31761,"49014":31689,"49015":31716,"49016":31707,"49017":31713,"49018":31721,"49019":31718,"49020":31957,"49021":31958,"49022":32266,"49057":32273,"49058":32264,"49059":32283,"49060":32291,"49061":32286,"49062":32285,"49063":32265,"49064":32272,"49065":32633,"49066":32690,"49067":32752,"49068":32753,"49069":32750,"49070":32808,"49071":33203,"49072":33193,"49073":33192,"49074":33275,"49075":33288,"49076":33368,"49077":33369,"49078":34122,"49079":34137,"49080":34120,"49081":34152,"49082":34153,"49083":34115,"49084":34121,"49085":34157,"49086":34154,"49087":34142,"49088":34691,"49089":34719,"49090":34718,"49091":34722,"49092":34701,"49093":34913,"49094":35114,"49095":35122,"49096":35109,"49097":35115,"49098":35105,"49099":35242,"49100":35238,"49101":35558,"49102":35578,"49103":35563,"49104":35569,"49105":35584,"49106":35548,"49107":35559,"49108":35566,"49109":35582,"49110":35585,"49111":35586,"49112":35575,"49113":35565,"49114":35571,"49115":35574,"49116":35580,"49117":35947,"49118":35949,"49119":35987,"49120":36084,"49121":36420,"49122":36401,"49123":36404,"49124":36418,"49125":36409,"49126":36405,"49127":36667,"49128":36655,"49129":36664,"49130":36659,"49131":36776,"49132":36774,"49133":36981,"49134":36980,"49135":36984,"49136":36978,"49137":36988,"49138":36986,"49139":37172,"49140":37266,"49141":37664,"49142":37686,"49143":37624,"49144":37683,"49145":37679,"49146":37666,"49147":37628,"49148":37675,"49149":37636,"49150":37658,"49216":37648,"49217":37670,"49218":37665,"49219":37653,"49220":37678,"49221":37657,"49222":38331,"49223":38567,"49224":38568,"49225":38570,"49226":38613,"49227":38670,"49228":38673,"49229":38678,"49230":38669,"49231":38675,"49232":38671,"49233":38747,"49234":38748,"49235":38758,"49236":38808,"49237":38960,"49238":38968,"49239":38971,"49240":38967,"49241":38957,"49242":38969,"49243":38948,"49244":39184,"49245":39208,"49246":39198,"49247":39195,"49248":39201,"49249":39194,"49250":39405,"49251":39394,"49252":39409,"49253":39608,"49254":39612,"49255":39675,"49256":39661,"49257":39720,"49258":39825,"49259":40213,"49260":40227,"49261":40230,"49262":40232,"49263":40210,"49264":40219,"49265":40664,"49266":40660,"49267":40845,"49268":40860,"49269":20778,"49270":20767,"49271":20769,"49272":20786,"49273":21237,"49274":22158,"49275":22144,"49276":22160,"49277":22149,"49278":22151,"49313":22159,"49314":22741,"49315":22739,"49316":22737,"49317":22734,"49318":23344,"49319":23338,"49320":23332,"49321":23418,"49322":23607,"49323":23656,"49324":23996,"49325":23994,"49326":23997,"49327":23992,"49328":24171,"49329":24396,"49330":24509,"49331":25033,"49332":25026,"49333":25031,"49334":25062,"49335":25035,"49336":25138,"49337":25140,"49338":25806,"49339":25802,"49340":25816,"49341":25824,"49342":25840,"49343":25830,"49344":25836,"49345":25841,"49346":25826,"49347":25837,"49348":25986,"49349":25987,"49350":26329,"49351":26326,"49352":27264,"49353":27284,"49354":27268,"49355":27298,"49356":27292,"49357":27355,"49358":27299,"49359":27262,"49360":27287,"49361":27280,"49362":27296,"49363":27484,"49364":27566,"49365":27610,"49366":27656,"49367":28632,"49368":28657,"49369":28639,"49370":28640,"49371":28635,"49372":28644,"49373":28651,"49374":28655,"49375":28544,"49376":28652,"49377":28641,"49378":28649,"49379":28629,"49380":28654,"49381":28656,"49382":29159,"49383":29151,"49384":29166,"49385":29158,"49386":29157,"49387":29165,"49388":29164,"49389":29172,"49390":29152,"49391":29237,"49392":29254,"49393":29552,"49394":29554,"49395":29865,"49396":29872,"49397":29862,"49398":29864,"49399":30278,"49400":30274,"49401":30284,"49402":30442,"49403":30643,"49404":30634,"49405":30640,"49406":30636,"49472":30631,"49473":30637,"49474":30703,"49475":30967,"49476":30970,"49477":30964,"49478":30959,"49479":30977,"49480":31143,"49481":31146,"49482":31319,"49483":31423,"49484":31751,"49485":31757,"49486":31742,"49487":31735,"49488":31756,"49489":31712,"49490":31968,"49491":31964,"49492":31966,"49493":31970,"49494":31967,"49495":31961,"49496":31965,"49497":32302,"49498":32318,"49499":32326,"49500":32311,"49501":32306,"49502":32323,"49503":32299,"49504":32317,"49505":32305,"49506":32325,"49507":32321,"49508":32308,"49509":32313,"49510":32328,"49511":32309,"49512":32319,"49513":32303,"49514":32580,"49515":32755,"49516":32764,"49517":32881,"49518":32882,"49519":32880,"49520":32879,"49521":32883,"49522":33222,"49523":33219,"49524":33210,"49525":33218,"49526":33216,"49527":33215,"49528":33213,"49529":33225,"49530":33214,"49531":33256,"49532":33289,"49533":33393,"49534":34218,"49569":34180,"49570":34174,"49571":34204,"49572":34193,"49573":34196,"49574":34223,"49575":34203,"49576":34183,"49577":34216,"49578":34186,"49579":34407,"49580":34752,"49581":34769,"49582":34739,"49583":34770,"49584":34758,"49585":34731,"49586":34747,"49587":34746,"49588":34760,"49589":34763,"49590":35131,"49591":35126,"49592":35140,"49593":35128,"49594":35133,"49595":35244,"49596":35598,"49597":35607,"49598":35609,"49599":35611,"49600":35594,"49601":35616,"49602":35613,"49603":35588,"49604":35600,"49605":35905,"49606":35903,"49607":35955,"49608":36090,"49609":36093,"49610":36092,"49611":36088,"49612":36091,"49613":36264,"49614":36425,"49615":36427,"49616":36424,"49617":36426,"49618":36676,"49619":36670,"49620":36674,"49621":36677,"49622":36671,"49623":36991,"49624":36989,"49625":36996,"49626":36993,"49627":36994,"49628":36992,"49629":37177,"49630":37283,"49631":37278,"49632":37276,"49633":37709,"49634":37762,"49635":37672,"49636":37749,"49637":37706,"49638":37733,"49639":37707,"49640":37656,"49641":37758,"49642":37740,"49643":37723,"49644":37744,"49645":37722,"49646":37716,"49647":38346,"49648":38347,"49649":38348,"49650":38344,"49651":38342,"49652":38577,"49653":38584,"49654":38614,"49655":38684,"49656":38686,"49657":38816,"49658":38867,"49659":38982,"49660":39094,"49661":39221,"49662":39425,"49728":39423,"49729":39854,"49730":39851,"49731":39850,"49732":39853,"49733":40251,"49734":40255,"49735":40587,"49736":40655,"49737":40670,"49738":40668,"49739":40669,"49740":40667,"49741":40766,"49742":40779,"49743":21474,"49744":22165,"49745":22190,"49746":22745,"49747":22744,"49748":23352,"49749":24413,"49750":25059,"49751":25139,"49752":25844,"49753":25842,"49754":25854,"49755":25862,"49756":25850,"49757":25851,"49758":25847,"49759":26039,"49760":26332,"49761":26406,"49762":27315,"49763":27308,"49764":27331,"49765":27323,"49766":27320,"49767":27330,"49768":27310,"49769":27311,"49770":27487,"49771":27512,"49772":27567,"49773":28681,"49774":28683,"49775":28670,"49776":28678,"49777":28666,"49778":28689,"49779":28687,"49780":29179,"49781":29180,"49782":29182,"49783":29176,"49784":29559,"49785":29557,"49786":29863,"49787":29887,"49788":29973,"49789":30294,"49790":30296,"49825":30290,"49826":30653,"49827":30655,"49828":30651,"49829":30652,"49830":30990,"49831":31150,"49832":31329,"49833":31330,"49834":31328,"49835":31428,"49836":31429,"49837":31787,"49838":31783,"49839":31786,"49840":31774,"49841":31779,"49842":31777,"49843":31975,"49844":32340,"49845":32341,"49846":32350,"49847":32346,"49848":32353,"49849":32338,"49850":32345,"49851":32584,"49852":32761,"49853":32763,"49854":32887,"49855":32886,"49856":33229,"49857":33231,"49858":33290,"49859":34255,"49860":34217,"49861":34253,"49862":34256,"49863":34249,"49864":34224,"49865":34234,"49866":34233,"49867":34214,"49868":34799,"49869":34796,"49870":34802,"49871":34784,"49872":35206,"49873":35250,"49874":35316,"49875":35624,"49876":35641,"49877":35628,"49878":35627,"49879":35920,"49880":36101,"49881":36441,"49882":36451,"49883":36454,"49884":36452,"49885":36447,"49886":36437,"49887":36544,"49888":36681,"49889":36685,"49890":36999,"49891":36995,"49892":37000,"49893":37291,"49894":37292,"49895":37328,"49896":37780,"49897":37770,"49898":37782,"49899":37794,"49900":37811,"49901":37806,"49902":37804,"49903":37808,"49904":37784,"49905":37786,"49906":37783,"49907":38356,"49908":38358,"49909":38352,"49910":38357,"49911":38626,"49912":38620,"49913":38617,"49914":38619,"49915":38622,"49916":38692,"49917":38819,"49918":38822,"49984":38829,"49985":38905,"49986":38989,"49987":38991,"49988":38988,"49989":38990,"49990":38995,"49991":39098,"49992":39230,"49993":39231,"49994":39229,"49995":39214,"49996":39333,"49997":39438,"49998":39617,"49999":39683,"50000":39686,"50001":39759,"50002":39758,"50003":39757,"50004":39882,"50005":39881,"50006":39933,"50007":39880,"50008":39872,"50009":40273,"50010":40285,"50011":40288,"50012":40672,"50013":40725,"50014":40748,"50015":20787,"50016":22181,"50017":22750,"50018":22751,"50019":22754,"50020":23541,"50021":40848,"50022":24300,"50023":25074,"50024":25079,"50025":25078,"50026":25077,"50027":25856,"50028":25871,"50029":26336,"50030":26333,"50031":27365,"50032":27357,"50033":27354,"50034":27347,"50035":28699,"50036":28703,"50037":28712,"50038":28698,"50039":28701,"50040":28693,"50041":28696,"50042":29190,"50043":29197,"50044":29272,"50045":29346,"50046":29560,"50081":29562,"50082":29885,"50083":29898,"50084":29923,"50085":30087,"50086":30086,"50087":30303,"50088":30305,"50089":30663,"50090":31001,"50091":31153,"50092":31339,"50093":31337,"50094":31806,"50095":31807,"50096":31800,"50097":31805,"50098":31799,"50099":31808,"50100":32363,"50101":32365,"50102":32377,"50103":32361,"50104":32362,"50105":32645,"50106":32371,"50107":32694,"50108":32697,"50109":32696,"50110":33240,"50111":34281,"50112":34269,"50113":34282,"50114":34261,"50115":34276,"50116":34277,"50117":34295,"50118":34811,"50119":34821,"50120":34829,"50121":34809,"50122":34814,"50123":35168,"50124":35167,"50125":35158,"50126":35166,"50127":35649,"50128":35676,"50129":35672,"50130":35657,"50131":35674,"50132":35662,"50133":35663,"50134":35654,"50135":35673,"50136":36104,"50137":36106,"50138":36476,"50139":36466,"50140":36487,"50141":36470,"50142":36460,"50143":36474,"50144":36468,"50145":36692,"50146":36686,"50147":36781,"50148":37002,"50149":37003,"50150":37297,"50151":37294,"50152":37857,"50153":37841,"50154":37855,"50155":37827,"50156":37832,"50157":37852,"50158":37853,"50159":37846,"50160":37858,"50161":37837,"50162":37848,"50163":37860,"50164":37847,"50165":37864,"50166":38364,"50167":38580,"50168":38627,"50169":38698,"50170":38695,"50171":38753,"50172":38876,"50173":38907,"50174":39006,"50240":39000,"50241":39003,"50242":39100,"50243":39237,"50244":39241,"50245":39446,"50246":39449,"50247":39693,"50248":39912,"50249":39911,"50250":39894,"50251":39899,"50252":40329,"50253":40289,"50254":40306,"50255":40298,"50256":40300,"50257":40594,"50258":40599,"50259":40595,"50260":40628,"50261":21240,"50262":22184,"50263":22199,"50264":22198,"50265":22196,"50266":22204,"50267":22756,"50268":23360,"50269":23363,"50270":23421,"50271":23542,"50272":24009,"50273":25080,"50274":25082,"50275":25880,"50276":25876,"50277":25881,"50278":26342,"50279":26407,"50280":27372,"50281":28734,"50282":28720,"50283":28722,"50284":29200,"50285":29563,"50286":29903,"50287":30306,"50288":30309,"50289":31014,"50290":31018,"50291":31020,"50292":31019,"50293":31431,"50294":31478,"50295":31820,"50296":31811,"50297":31821,"50298":31983,"50299":31984,"50300":36782,"50301":32381,"50302":32380,"50337":32386,"50338":32588,"50339":32768,"50340":33242,"50341":33382,"50342":34299,"50343":34297,"50344":34321,"50345":34298,"50346":34310,"50347":34315,"50348":34311,"50349":34314,"50350":34836,"50351":34837,"50352":35172,"50353":35258,"50354":35320,"50355":35696,"50356":35692,"50357":35686,"50358":35695,"50359":35679,"50360":35691,"50361":36111,"50362":36109,"50363":36489,"50364":36481,"50365":36485,"50366":36482,"50367":37300,"50368":37323,"50369":37912,"50370":37891,"50371":37885,"50372":38369,"50373":38704,"50374":39108,"50375":39250,"50376":39249,"50377":39336,"50378":39467,"50379":39472,"50380":39479,"50381":39477,"50382":39955,"50383":39949,"50384":40569,"50385":40629,"50386":40680,"50387":40751,"50388":40799,"50389":40803,"50390":40801,"50391":20791,"50392":20792,"50393":22209,"50394":22208,"50395":22210,"50396":22804,"50397":23660,"50398":24013,"50399":25084,"50400":25086,"50401":25885,"50402":25884,"50403":26005,"50404":26345,"50405":27387,"50406":27396,"50407":27386,"50408":27570,"50409":28748,"50410":29211,"50411":29351,"50412":29910,"50413":29908,"50414":30313,"50415":30675,"50416":31824,"50417":32399,"50418":32396,"50419":32700,"50420":34327,"50421":34349,"50422":34330,"50423":34851,"50424":34850,"50425":34849,"50426":34847,"50427":35178,"50428":35180,"50429":35261,"50430":35700,"50496":35703,"50497":35709,"50498":36115,"50499":36490,"50500":36493,"50501":36491,"50502":36703,"50503":36783,"50504":37306,"50505":37934,"50506":37939,"50507":37941,"50508":37946,"50509":37944,"50510":37938,"50511":37931,"50512":38370,"50513":38712,"50514":38713,"50515":38706,"50516":38911,"50517":39015,"50518":39013,"50519":39255,"50520":39493,"50521":39491,"50522":39488,"50523":39486,"50524":39631,"50525":39764,"50526":39761,"50527":39981,"50528":39973,"50529":40367,"50530":40372,"50531":40386,"50532":40376,"50533":40605,"50534":40687,"50535":40729,"50536":40796,"50537":40806,"50538":40807,"50539":20796,"50540":20795,"50541":22216,"50542":22218,"50543":22217,"50544":23423,"50545":24020,"50546":24018,"50547":24398,"50548":25087,"50549":25892,"50550":27402,"50551":27489,"50552":28753,"50553":28760,"50554":29568,"50555":29924,"50556":30090,"50557":30318,"50558":30316,"50593":31155,"50594":31840,"50595":31839,"50596":32894,"50597":32893,"50598":33247,"50599":35186,"50600":35183,"50601":35324,"50602":35712,"50603":36118,"50604":36119,"50605":36497,"50606":36499,"50607":36705,"50608":37192,"50609":37956,"50610":37969,"50611":37970,"50612":38717,"50613":38718,"50614":38851,"50615":38849,"50616":39019,"50617":39253,"50618":39509,"50619":39501,"50620":39634,"50621":39706,"50622":40009,"50623":39985,"50624":39998,"50625":39995,"50626":40403,"50627":40407,"50628":40756,"50629":40812,"50630":40810,"50631":40852,"50632":22220,"50633":24022,"50634":25088,"50635":25891,"50636":25899,"50637":25898,"50638":26348,"50639":27408,"50640":29914,"50641":31434,"50642":31844,"50643":31843,"50644":31845,"50645":32403,"50646":32406,"50647":32404,"50648":33250,"50649":34360,"50650":34367,"50651":34865,"50652":35722,"50653":37008,"50654":37007,"50655":37987,"50656":37984,"50657":37988,"50658":38760,"50659":39023,"50660":39260,"50661":39514,"50662":39515,"50663":39511,"50664":39635,"50665":39636,"50666":39633,"50667":40020,"50668":40023,"50669":40022,"50670":40421,"50671":40607,"50672":40692,"50673":22225,"50674":22761,"50675":25900,"50676":28766,"50677":30321,"50678":30322,"50679":30679,"50680":32592,"50681":32648,"50682":34870,"50683":34873,"50684":34914,"50685":35731,"50686":35730,"50752":35734,"50753":33399,"50754":36123,"50755":37312,"50756":37994,"50757":38722,"50758":38728,"50759":38724,"50760":38854,"50761":39024,"50762":39519,"50763":39714,"50764":39768,"50765":40031,"50766":40441,"50767":40442,"50768":40572,"50769":40573,"50770":40711,"50771":40823,"50772":40818,"50773":24307,"50774":27414,"50775":28771,"50776":31852,"50777":31854,"50778":34875,"50779":35264,"50780":36513,"50781":37313,"50782":38002,"50783":38000,"50784":39025,"50785":39262,"50786":39638,"50787":39715,"50788":40652,"50789":28772,"50790":30682,"50791":35738,"50792":38007,"50793":38857,"50794":39522,"50795":39525,"50796":32412,"50797":35740,"50798":36522,"50799":37317,"50800":38013,"50801":38014,"50802":38012,"50803":40055,"50804":40056,"50805":40695,"50806":35924,"50807":38015,"50808":40474,"50809":29224,"50810":39530,"50811":39729,"50812":40475,"50813":40478,"50814":31858,"50849":9312,"50850":9313,"50851":9314,"50852":9315,"50853":9316,"50854":9317,"50855":9318,"50856":9319,"50857":9320,"50858":9321,"50859":9332,"50860":9333,"50861":9334,"50862":9335,"50863":9336,"50864":9337,"50865":9338,"50866":9339,"50867":9340,"50868":9341,"50869":8560,"50870":8561,"50871":8562,"50872":8563,"50873":8564,"50874":8565,"50875":8566,"50876":8567,"50877":8568,"50878":8569,"50879":20022,"50880":20031,"50881":20101,"50882":20128,"50883":20866,"50884":20886,"50885":20907,"50886":21241,"50887":21304,"50888":21353,"50889":21430,"50890":22794,"50891":23424,"50892":24027,"50893":24186,"50894":24191,"50895":24308,"50896":24400,"50897":24417,"50898":25908,"50899":26080,"50900":30098,"50901":30326,"50902":36789,"50903":38582,"50904":168,"50905":710,"50906":12541,"50907":12542,"50908":12445,"50909":12446,"50910":12291,"50911":20189,"50912":12293,"50913":12294,"50914":12295,"50915":12540,"50916":65339,"50917":65341,"50918":10045,"50919":12353,"50920":12354,"50921":12355,"50922":12356,"50923":12357,"50924":12358,"50925":12359,"50926":12360,"50927":12361,"50928":12362,"50929":12363,"50930":12364,"50931":12365,"50932":12366,"50933":12367,"50934":12368,"50935":12369,"50936":12370,"50937":12371,"50938":12372,"50939":12373,"50940":12374,"50941":12375,"50942":12376,"51008":12377,"51009":12378,"51010":12379,"51011":12380,"51012":12381,"51013":12382,"51014":12383,"51015":12384,"51016":12385,"51017":12386,"51018":12387,"51019":12388,"51020":12389,"51021":12390,"51022":12391,"51023":12392,"51024":12393,"51025":12394,"51026":12395,"51027":12396,"51028":12397,"51029":12398,"51030":12399,"51031":12400,"51032":12401,"51033":12402,"51034":12403,"51035":12404,"51036":12405,"51037":12406,"51038":12407,"51039":12408,"51040":12409,"51041":12410,"51042":12411,"51043":12412,"51044":12413,"51045":12414,"51046":12415,"51047":12416,"51048":12417,"51049":12418,"51050":12419,"51051":12420,"51052":12421,"51053":12422,"51054":12423,"51055":12424,"51056":12425,"51057":12426,"51058":12427,"51059":12428,"51060":12429,"51061":12430,"51062":12431,"51063":12432,"51064":12433,"51065":12434,"51066":12435,"51067":12449,"51068":12450,"51069":12451,"51070":12452,"51105":12453,"51106":12454,"51107":12455,"51108":12456,"51109":12457,"51110":12458,"51111":12459,"51112":12460,"51113":12461,"51114":12462,"51115":12463,"51116":12464,"51117":12465,"51118":12466,"51119":12467,"51120":12468,"51121":12469,"51122":12470,"51123":12471,"51124":12472,"51125":12473,"51126":12474,"51127":12475,"51128":12476,"51129":12477,"51130":12478,"51131":12479,"51132":12480,"51133":12481,"51134":12482,"51135":12483,"51136":12484,"51137":12485,"51138":12486,"51139":12487,"51140":12488,"51141":12489,"51142":12490,"51143":12491,"51144":12492,"51145":12493,"51146":12494,"51147":12495,"51148":12496,"51149":12497,"51150":12498,"51151":12499,"51152":12500,"51153":12501,"51154":12502,"51155":12503,"51156":12504,"51157":12505,"51158":12506,"51159":12507,"51160":12508,"51161":12509,"51162":12510,"51163":12511,"51164":12512,"51165":12513,"51166":12514,"51167":12515,"51168":12516,"51169":12517,"51170":12518,"51171":12519,"51172":12520,"51173":12521,"51174":12522,"51175":12523,"51176":12524,"51177":12525,"51178":12526,"51179":12527,"51180":12528,"51181":12529,"51182":12530,"51183":12531,"51184":12532,"51185":12533,"51186":12534,"51187":1040,"51188":1041,"51189":1042,"51190":1043,"51191":1044,"51192":1045,"51193":1025,"51194":1046,"51195":1047,"51196":1048,"51197":1049,"51198":1050,"51264":1051,"51265":1052,"51266":1053,"51267":1054,"51268":1055,"51269":1056,"51270":1057,"51271":1058,"51272":1059,"51273":1060,"51274":1061,"51275":1062,"51276":1063,"51277":1064,"51278":1065,"51279":1066,"51280":1067,"51281":1068,"51282":1069,"51283":1070,"51284":1071,"51285":1072,"51286":1073,"51287":1074,"51288":1075,"51289":1076,"51290":1077,"51291":1105,"51292":1078,"51293":1079,"51294":1080,"51295":1081,"51296":1082,"51297":1083,"51298":1084,"51299":1085,"51300":1086,"51301":1087,"51302":1088,"51303":1089,"51304":1090,"51305":1091,"51306":1092,"51307":1093,"51308":1094,"51309":1095,"51310":1096,"51311":1097,"51312":1098,"51313":1099,"51314":1100,"51315":1101,"51316":1102,"51317":1103,"51318":8679,"51319":8632,"51320":8633,"51321":12751,"51322":63462,"51323":20058,"51324":63464,"51325":20994,"51326":17553,"51361":40880,"51362":20872,"51363":40881,"51364":63470,"51365":63471,"51366":63472,"51367":63473,"51368":63474,"51369":63475,"51370":63476,"51371":63477,"51372":63478,"51373":63479,"51374":63480,"51375":63481,"51376":63482,"51377":12443,"51378":12444,"51379":12436,"51380":12535,"51381":12536,"51382":12537,"51383":12538,"51384":12539,"51385":65377,"51386":65378,"51387":65379,"51388":65380,"51389":65381,"51390":65382,"51391":65383,"51392":65384,"51393":65385,"51394":65386,"51395":65387,"51396":65388,"51397":65389,"51398":65390,"51399":65391,"51400":65392,"51401":65393,"51402":65394,"51403":65395,"51404":65396,"51405":65506,"51406":65508,"51407":65287,"51408":65282,"51409":12849,"51410":8470,"51411":8481,"51412":65397,"51413":65398,"51414":65399,"51415":65400,"51416":65401,"51417":65402,"51418":65403,"51419":65404,"51420":65405,"51421":65406,"51422":65407,"51423":65408,"51424":65409,"51425":65410,"51426":65411,"51427":65412,"51428":65413,"51429":65414,"51430":65415,"51431":65416,"51432":65417,"51433":65418,"51434":65419,"51435":65420,"51436":65421,"51437":65422,"51438":65423,"51439":65424,"51440":65425,"51441":65426,"51442":65427,"51443":65428,"51444":65429,"51445":65430,"51446":65431,"51447":65432,"51448":65433,"51449":65434,"51450":65435,"51451":65436,"51452":65437,"51453":65438,"51454":65439,"51520":20034,"51521":20060,"51522":20981,"51523":21274,"51524":21378,"51525":19975,"51526":19980,"51527":20039,"51528":20109,"51529":22231,"51530":64012,"51531":23662,"51532":24435,"51533":19983,"51534":20871,"51535":19982,"51536":20014,"51537":20115,"51538":20162,"51539":20169,"51540":20168,"51541":20888,"51542":21244,"51543":21356,"51544":21433,"51545":22304,"51546":22787,"51547":22828,"51548":23568,"51549":24063,"51550":26081,"51551":27571,"51552":27596,"51553":27668,"51554":29247,"51555":20017,"51556":20028,"51557":20200,"51558":20188,"51559":20201,"51560":20193,"51561":20189,"51562":20186,"51563":21004,"51564":21276,"51565":21324,"51566":22306,"51567":22307,"51568":22807,"51569":22831,"51570":23425,"51571":23428,"51572":23570,"51573":23611,"51574":23668,"51575":23667,"51576":24068,"51577":24192,"51578":24194,"51579":24521,"51580":25097,"51581":25168,"51582":27669,"51617":27702,"51618":27715,"51619":27711,"51620":27707,"51621":29358,"51622":29360,"51623":29578,"51624":31160,"51625":32906,"51626":38430,"51627":20238,"51628":20248,"51629":20268,"51630":20213,"51631":20244,"51632":20209,"51633":20224,"51634":20215,"51635":20232,"51636":20253,"51637":20226,"51638":20229,"51639":20258,"51640":20243,"51641":20228,"51642":20212,"51643":20242,"51644":20913,"51645":21011,"51646":21001,"51647":21008,"51648":21158,"51649":21282,"51650":21279,"51651":21325,"51652":21386,"51653":21511,"51654":22241,"51655":22239,"51656":22318,"51657":22314,"51658":22324,"51659":22844,"51660":22912,"51661":22908,"51662":22917,"51663":22907,"51664":22910,"51665":22903,"51666":22911,"51667":23382,"51668":23573,"51669":23589,"51670":23676,"51671":23674,"51672":23675,"51673":23678,"51674":24031,"51675":24181,"51676":24196,"51677":24322,"51678":24346,"51679":24436,"51680":24533,"51681":24532,"51682":24527,"51683":25180,"51684":25182,"51685":25188,"51686":25185,"51687":25190,"51688":25186,"51689":25177,"51690":25184,"51691":25178,"51692":25189,"51693":26095,"51694":26094,"51695":26430,"51696":26425,"51697":26424,"51698":26427,"51699":26426,"51700":26431,"51701":26428,"51702":26419,"51703":27672,"51704":27718,"51705":27730,"51706":27740,"51707":27727,"51708":27722,"51709":27732,"51710":27723,"51776":27724,"51777":28785,"51778":29278,"51779":29364,"51780":29365,"51781":29582,"51782":29994,"51783":30335,"51784":31349,"51785":32593,"51786":33400,"51787":33404,"51788":33408,"51789":33405,"51790":33407,"51791":34381,"51792":35198,"51793":37017,"51794":37015,"51795":37016,"51796":37019,"51797":37012,"51798":38434,"51799":38436,"51800":38432,"51801":38435,"51802":20310,"51803":20283,"51804":20322,"51805":20297,"51806":20307,"51807":20324,"51808":20286,"51809":20327,"51810":20306,"51811":20319,"51812":20289,"51813":20312,"51814":20269,"51815":20275,"51816":20287,"51817":20321,"51818":20879,"51819":20921,"51820":21020,"51821":21022,"51822":21025,"51823":21165,"51824":21166,"51825":21257,"51826":21347,"51827":21362,"51828":21390,"51829":21391,"51830":21552,"51831":21559,"51832":21546,"51833":21588,"51834":21573,"51835":21529,"51836":21532,"51837":21541,"51838":21528,"51873":21565,"51874":21583,"51875":21569,"51876":21544,"51877":21540,"51878":21575,"51879":22254,"51880":22247,"51881":22245,"51882":22337,"51883":22341,"51884":22348,"51885":22345,"51886":22347,"51887":22354,"51888":22790,"51889":22848,"51890":22950,"51891":22936,"51892":22944,"51893":22935,"51894":22926,"51895":22946,"51896":22928,"51897":22927,"51898":22951,"51899":22945,"51900":23438,"51901":23442,"51902":23592,"51903":23594,"51904":23693,"51905":23695,"51906":23688,"51907":23691,"51908":23689,"51909":23698,"51910":23690,"51911":23686,"51912":23699,"51913":23701,"51914":24032,"51915":24074,"51916":24078,"51917":24203,"51918":24201,"51919":24204,"51920":24200,"51921":24205,"51922":24325,"51923":24349,"51924":24440,"51925":24438,"51926":24530,"51927":24529,"51928":24528,"51929":24557,"51930":24552,"51931":24558,"51932":24563,"51933":24545,"51934":24548,"51935":24547,"51936":24570,"51937":24559,"51938":24567,"51939":24571,"51940":24576,"51941":24564,"51942":25146,"51943":25219,"51944":25228,"51945":25230,"51946":25231,"51947":25236,"51948":25223,"51949":25201,"51950":25211,"51951":25210,"51952":25200,"51953":25217,"51954":25224,"51955":25207,"51956":25213,"51957":25202,"51958":25204,"51959":25911,"51960":26096,"51961":26100,"51962":26099,"51963":26098,"51964":26101,"51965":26437,"51966":26439,"52032":26457,"52033":26453,"52034":26444,"52035":26440,"52036":26461,"52037":26445,"52038":26458,"52039":26443,"52040":27600,"52041":27673,"52042":27674,"52043":27768,"52044":27751,"52045":27755,"52046":27780,"52047":27787,"52048":27791,"52049":27761,"52050":27759,"52051":27753,"52052":27802,"52053":27757,"52054":27783,"52055":27797,"52056":27804,"52057":27750,"52058":27763,"52059":27749,"52060":27771,"52061":27790,"52062":28788,"52063":28794,"52064":29283,"52065":29375,"52066":29373,"52067":29379,"52068":29382,"52069":29377,"52070":29370,"52071":29381,"52072":29589,"52073":29591,"52074":29587,"52075":29588,"52076":29586,"52077":30010,"52078":30009,"52079":30100,"52080":30101,"52081":30337,"52082":31037,"52083":32820,"52084":32917,"52085":32921,"52086":32912,"52087":32914,"52088":32924,"52089":33424,"52090":33423,"52091":33413,"52092":33422,"52093":33425,"52094":33427,"52129":33418,"52130":33411,"52131":33412,"52132":35960,"52133":36809,"52134":36799,"52135":37023,"52136":37025,"52137":37029,"52138":37022,"52139":37031,"52140":37024,"52141":38448,"52142":38440,"52143":38447,"52144":38445,"52145":20019,"52146":20376,"52147":20348,"52148":20357,"52149":20349,"52150":20352,"52151":20359,"52152":20342,"52153":20340,"52154":20361,"52155":20356,"52156":20343,"52157":20300,"52158":20375,"52159":20330,"52160":20378,"52161":20345,"52162":20353,"52163":20344,"52164":20368,"52165":20380,"52166":20372,"52167":20382,"52168":20370,"52169":20354,"52170":20373,"52171":20331,"52172":20334,"52173":20894,"52174":20924,"52175":20926,"52176":21045,"52177":21042,"52178":21043,"52179":21062,"52180":21041,"52181":21180,"52182":21258,"52183":21259,"52184":21308,"52185":21394,"52186":21396,"52187":21639,"52188":21631,"52189":21633,"52190":21649,"52191":21634,"52192":21640,"52193":21611,"52194":21626,"52195":21630,"52196":21605,"52197":21612,"52198":21620,"52199":21606,"52200":21645,"52201":21615,"52202":21601,"52203":21600,"52204":21656,"52205":21603,"52206":21607,"52207":21604,"52208":22263,"52209":22265,"52210":22383,"52211":22386,"52212":22381,"52213":22379,"52214":22385,"52215":22384,"52216":22390,"52217":22400,"52218":22389,"52219":22395,"52220":22387,"52221":22388,"52222":22370,"52288":22376,"52289":22397,"52290":22796,"52291":22853,"52292":22965,"52293":22970,"52294":22991,"52295":22990,"52296":22962,"52297":22988,"52298":22977,"52299":22966,"52300":22972,"52301":22979,"52302":22998,"52303":22961,"52304":22973,"52305":22976,"52306":22984,"52307":22964,"52308":22983,"52309":23394,"52310":23397,"52311":23443,"52312":23445,"52313":23620,"52314":23623,"52315":23726,"52316":23716,"52317":23712,"52318":23733,"52319":23727,"52320":23720,"52321":23724,"52322":23711,"52323":23715,"52324":23725,"52325":23714,"52326":23722,"52327":23719,"52328":23709,"52329":23717,"52330":23734,"52331":23728,"52332":23718,"52333":24087,"52334":24084,"52335":24089,"52336":24360,"52337":24354,"52338":24355,"52339":24356,"52340":24404,"52341":24450,"52342":24446,"52343":24445,"52344":24542,"52345":24549,"52346":24621,"52347":24614,"52348":24601,"52349":24626,"52350":24587,"52385":24628,"52386":24586,"52387":24599,"52388":24627,"52389":24602,"52390":24606,"52391":24620,"52392":24610,"52393":24589,"52394":24592,"52395":24622,"52396":24595,"52397":24593,"52398":24588,"52399":24585,"52400":24604,"52401":25108,"52402":25149,"52403":25261,"52404":25268,"52405":25297,"52406":25278,"52407":25258,"52408":25270,"52409":25290,"52410":25262,"52411":25267,"52412":25263,"52413":25275,"52414":25257,"52415":25264,"52416":25272,"52417":25917,"52418":26024,"52419":26043,"52420":26121,"52421":26108,"52422":26116,"52423":26130,"52424":26120,"52425":26107,"52426":26115,"52427":26123,"52428":26125,"52429":26117,"52430":26109,"52431":26129,"52432":26128,"52433":26358,"52434":26378,"52435":26501,"52436":26476,"52437":26510,"52438":26514,"52439":26486,"52440":26491,"52441":26520,"52442":26502,"52443":26500,"52444":26484,"52445":26509,"52446":26508,"52447":26490,"52448":26527,"52449":26513,"52450":26521,"52451":26499,"52452":26493,"52453":26497,"52454":26488,"52455":26489,"52456":26516,"52457":27429,"52458":27520,"52459":27518,"52460":27614,"52461":27677,"52462":27795,"52463":27884,"52464":27883,"52465":27886,"52466":27865,"52467":27830,"52468":27860,"52469":27821,"52470":27879,"52471":27831,"52472":27856,"52473":27842,"52474":27834,"52475":27843,"52476":27846,"52477":27885,"52478":27890,"52544":27858,"52545":27869,"52546":27828,"52547":27786,"52548":27805,"52549":27776,"52550":27870,"52551":27840,"52552":27952,"52553":27853,"52554":27847,"52555":27824,"52556":27897,"52557":27855,"52558":27881,"52559":27857,"52560":28820,"52561":28824,"52562":28805,"52563":28819,"52564":28806,"52565":28804,"52566":28817,"52567":28822,"52568":28802,"52569":28826,"52570":28803,"52571":29290,"52572":29398,"52573":29387,"52574":29400,"52575":29385,"52576":29404,"52577":29394,"52578":29396,"52579":29402,"52580":29388,"52581":29393,"52582":29604,"52583":29601,"52584":29613,"52585":29606,"52586":29602,"52587":29600,"52588":29612,"52589":29597,"52590":29917,"52591":29928,"52592":30015,"52593":30016,"52594":30014,"52595":30092,"52596":30104,"52597":30383,"52598":30451,"52599":30449,"52600":30448,"52601":30453,"52602":30712,"52603":30716,"52604":30713,"52605":30715,"52606":30714,"52641":30711,"52642":31042,"52643":31039,"52644":31173,"52645":31352,"52646":31355,"52647":31483,"52648":31861,"52649":31997,"52650":32821,"52651":32911,"52652":32942,"52653":32931,"52654":32952,"52655":32949,"52656":32941,"52657":33312,"52658":33440,"52659":33472,"52660":33451,"52661":33434,"52662":33432,"52663":33435,"52664":33461,"52665":33447,"52666":33454,"52667":33468,"52668":33438,"52669":33466,"52670":33460,"52671":33448,"52672":33441,"52673":33449,"52674":33474,"52675":33444,"52676":33475,"52677":33462,"52678":33442,"52679":34416,"52680":34415,"52681":34413,"52682":34414,"52683":35926,"52684":36818,"52685":36811,"52686":36819,"52687":36813,"52688":36822,"52689":36821,"52690":36823,"52691":37042,"52692":37044,"52693":37039,"52694":37043,"52695":37040,"52696":38457,"52697":38461,"52698":38460,"52699":38458,"52700":38467,"52701":20429,"52702":20421,"52703":20435,"52704":20402,"52705":20425,"52706":20427,"52707":20417,"52708":20436,"52709":20444,"52710":20441,"52711":20411,"52712":20403,"52713":20443,"52714":20423,"52715":20438,"52716":20410,"52717":20416,"52718":20409,"52719":20460,"52720":21060,"52721":21065,"52722":21184,"52723":21186,"52724":21309,"52725":21372,"52726":21399,"52727":21398,"52728":21401,"52729":21400,"52730":21690,"52731":21665,"52732":21677,"52733":21669,"52734":21711,"52800":21699,"52801":33549,"52802":21687,"52803":21678,"52804":21718,"52805":21686,"52806":21701,"52807":21702,"52808":21664,"52809":21616,"52810":21692,"52811":21666,"52812":21694,"52813":21618,"52814":21726,"52815":21680,"52816":22453,"52817":22430,"52818":22431,"52819":22436,"52820":22412,"52821":22423,"52822":22429,"52823":22427,"52824":22420,"52825":22424,"52826":22415,"52827":22425,"52828":22437,"52829":22426,"52830":22421,"52831":22772,"52832":22797,"52833":22867,"52834":23009,"52835":23006,"52836":23022,"52837":23040,"52838":23025,"52839":23005,"52840":23034,"52841":23037,"52842":23036,"52843":23030,"52844":23012,"52845":23026,"52846":23031,"52847":23003,"52848":23017,"52849":23027,"52850":23029,"52851":23008,"52852":23038,"52853":23028,"52854":23021,"52855":23464,"52856":23628,"52857":23760,"52858":23768,"52859":23756,"52860":23767,"52861":23755,"52862":23771,"52897":23774,"52898":23770,"52899":23753,"52900":23751,"52901":23754,"52902":23766,"52903":23763,"52904":23764,"52905":23759,"52906":23752,"52907":23750,"52908":23758,"52909":23775,"52910":23800,"52911":24057,"52912":24097,"52913":24098,"52914":24099,"52915":24096,"52916":24100,"52917":24240,"52918":24228,"52919":24226,"52920":24219,"52921":24227,"52922":24229,"52923":24327,"52924":24366,"52925":24406,"52926":24454,"52927":24631,"52928":24633,"52929":24660,"52930":24690,"52931":24670,"52932":24645,"52933":24659,"52934":24647,"52935":24649,"52936":24667,"52937":24652,"52938":24640,"52939":24642,"52940":24671,"52941":24612,"52942":24644,"52943":24664,"52944":24678,"52945":24686,"52946":25154,"52947":25155,"52948":25295,"52949":25357,"52950":25355,"52951":25333,"52952":25358,"52953":25347,"52954":25323,"52955":25337,"52956":25359,"52957":25356,"52958":25336,"52959":25334,"52960":25344,"52961":25363,"52962":25364,"52963":25338,"52964":25365,"52965":25339,"52966":25328,"52967":25921,"52968":25923,"52969":26026,"52970":26047,"52971":26166,"52972":26145,"52973":26162,"52974":26165,"52975":26140,"52976":26150,"52977":26146,"52978":26163,"52979":26155,"52980":26170,"52981":26141,"52982":26164,"52983":26169,"52984":26158,"52985":26383,"52986":26384,"52987":26561,"52988":26610,"52989":26568,"52990":26554,"53056":26588,"53057":26555,"53058":26616,"53059":26584,"53060":26560,"53061":26551,"53062":26565,"53063":26603,"53064":26596,"53065":26591,"53066":26549,"53067":26573,"53068":26547,"53069":26615,"53070":26614,"53071":26606,"53072":26595,"53073":26562,"53074":26553,"53075":26574,"53076":26599,"53077":26608,"53078":26546,"53079":26620,"53080":26566,"53081":26605,"53082":26572,"53083":26542,"53084":26598,"53085":26587,"53086":26618,"53087":26569,"53088":26570,"53089":26563,"53090":26602,"53091":26571,"53092":27432,"53093":27522,"53094":27524,"53095":27574,"53096":27606,"53097":27608,"53098":27616,"53099":27680,"53100":27681,"53101":27944,"53102":27956,"53103":27949,"53104":27935,"53105":27964,"53106":27967,"53107":27922,"53108":27914,"53109":27866,"53110":27955,"53111":27908,"53112":27929,"53113":27962,"53114":27930,"53115":27921,"53116":27904,"53117":27933,"53118":27970,"53153":27905,"53154":27928,"53155":27959,"53156":27907,"53157":27919,"53158":27968,"53159":27911,"53160":27936,"53161":27948,"53162":27912,"53163":27938,"53164":27913,"53165":27920,"53166":28855,"53167":28831,"53168":28862,"53169":28849,"53170":28848,"53171":28833,"53172":28852,"53173":28853,"53174":28841,"53175":29249,"53176":29257,"53177":29258,"53178":29292,"53179":29296,"53180":29299,"53181":29294,"53182":29386,"53183":29412,"53184":29416,"53185":29419,"53186":29407,"53187":29418,"53188":29414,"53189":29411,"53190":29573,"53191":29644,"53192":29634,"53193":29640,"53194":29637,"53195":29625,"53196":29622,"53197":29621,"53198":29620,"53199":29675,"53200":29631,"53201":29639,"53202":29630,"53203":29635,"53204":29638,"53205":29624,"53206":29643,"53207":29932,"53208":29934,"53209":29998,"53210":30023,"53211":30024,"53212":30119,"53213":30122,"53214":30329,"53215":30404,"53216":30472,"53217":30467,"53218":30468,"53219":30469,"53220":30474,"53221":30455,"53222":30459,"53223":30458,"53224":30695,"53225":30696,"53226":30726,"53227":30737,"53228":30738,"53229":30725,"53230":30736,"53231":30735,"53232":30734,"53233":30729,"53234":30723,"53235":30739,"53236":31050,"53237":31052,"53238":31051,"53239":31045,"53240":31044,"53241":31189,"53242":31181,"53243":31183,"53244":31190,"53245":31182,"53246":31360,"53312":31358,"53313":31441,"53314":31488,"53315":31489,"53316":31866,"53317":31864,"53318":31865,"53319":31871,"53320":31872,"53321":31873,"53322":32003,"53323":32008,"53324":32001,"53325":32600,"53326":32657,"53327":32653,"53328":32702,"53329":32775,"53330":32782,"53331":32783,"53332":32788,"53333":32823,"53334":32984,"53335":32967,"53336":32992,"53337":32977,"53338":32968,"53339":32962,"53340":32976,"53341":32965,"53342":32995,"53343":32985,"53344":32988,"53345":32970,"53346":32981,"53347":32969,"53348":32975,"53349":32983,"53350":32998,"53351":32973,"53352":33279,"53353":33313,"53354":33428,"53355":33497,"53356":33534,"53357":33529,"53358":33543,"53359":33512,"53360":33536,"53361":33493,"53362":33594,"53363":33515,"53364":33494,"53365":33524,"53366":33516,"53367":33505,"53368":33522,"53369":33525,"53370":33548,"53371":33531,"53372":33526,"53373":33520,"53374":33514,"53409":33508,"53410":33504,"53411":33530,"53412":33523,"53413":33517,"53414":34423,"53415":34420,"53416":34428,"53417":34419,"53418":34881,"53419":34894,"53420":34919,"53421":34922,"53422":34921,"53423":35283,"53424":35332,"53425":35335,"53426":36210,"53427":36835,"53428":36833,"53429":36846,"53430":36832,"53431":37105,"53432":37053,"53433":37055,"53434":37077,"53435":37061,"53436":37054,"53437":37063,"53438":37067,"53439":37064,"53440":37332,"53441":37331,"53442":38484,"53443":38479,"53444":38481,"53445":38483,"53446":38474,"53447":38478,"53448":20510,"53449":20485,"53450":20487,"53451":20499,"53452":20514,"53453":20528,"53454":20507,"53455":20469,"53456":20468,"53457":20531,"53458":20535,"53459":20524,"53460":20470,"53461":20471,"53462":20503,"53463":20508,"53464":20512,"53465":20519,"53466":20533,"53467":20527,"53468":20529,"53469":20494,"53470":20826,"53471":20884,"53472":20883,"53473":20938,"53474":20932,"53475":20933,"53476":20936,"53477":20942,"53478":21089,"53479":21082,"53480":21074,"53481":21086,"53482":21087,"53483":21077,"53484":21090,"53485":21197,"53486":21262,"53487":21406,"53488":21798,"53489":21730,"53490":21783,"53491":21778,"53492":21735,"53493":21747,"53494":21732,"53495":21786,"53496":21759,"53497":21764,"53498":21768,"53499":21739,"53500":21777,"53501":21765,"53502":21745,"53568":21770,"53569":21755,"53570":21751,"53571":21752,"53572":21728,"53573":21774,"53574":21763,"53575":21771,"53576":22273,"53577":22274,"53578":22476,"53579":22578,"53580":22485,"53581":22482,"53582":22458,"53583":22470,"53584":22461,"53585":22460,"53586":22456,"53587":22454,"53588":22463,"53589":22471,"53590":22480,"53591":22457,"53592":22465,"53593":22798,"53594":22858,"53595":23065,"53596":23062,"53597":23085,"53598":23086,"53599":23061,"53600":23055,"53601":23063,"53602":23050,"53603":23070,"53604":23091,"53605":23404,"53606":23463,"53607":23469,"53608":23468,"53609":23555,"53610":23638,"53611":23636,"53612":23788,"53613":23807,"53614":23790,"53615":23793,"53616":23799,"53617":23808,"53618":23801,"53619":24105,"53620":24104,"53621":24232,"53622":24238,"53623":24234,"53624":24236,"53625":24371,"53626":24368,"53627":24423,"53628":24669,"53629":24666,"53630":24679,"53665":24641,"53666":24738,"53667":24712,"53668":24704,"53669":24722,"53670":24705,"53671":24733,"53672":24707,"53673":24725,"53674":24731,"53675":24727,"53676":24711,"53677":24732,"53678":24718,"53679":25113,"53680":25158,"53681":25330,"53682":25360,"53683":25430,"53684":25388,"53685":25412,"53686":25413,"53687":25398,"53688":25411,"53689":25572,"53690":25401,"53691":25419,"53692":25418,"53693":25404,"53694":25385,"53695":25409,"53696":25396,"53697":25432,"53698":25428,"53699":25433,"53700":25389,"53701":25415,"53702":25395,"53703":25434,"53704":25425,"53705":25400,"53706":25431,"53707":25408,"53708":25416,"53709":25930,"53710":25926,"53711":26054,"53712":26051,"53713":26052,"53714":26050,"53715":26186,"53716":26207,"53717":26183,"53718":26193,"53719":26386,"53720":26387,"53721":26655,"53722":26650,"53723":26697,"53724":26674,"53725":26675,"53726":26683,"53727":26699,"53728":26703,"53729":26646,"53730":26673,"53731":26652,"53732":26677,"53733":26667,"53734":26669,"53735":26671,"53736":26702,"53737":26692,"53738":26676,"53739":26653,"53740":26642,"53741":26644,"53742":26662,"53743":26664,"53744":26670,"53745":26701,"53746":26682,"53747":26661,"53748":26656,"53749":27436,"53750":27439,"53751":27437,"53752":27441,"53753":27444,"53754":27501,"53755":32898,"53756":27528,"53757":27622,"53758":27620,"53824":27624,"53825":27619,"53826":27618,"53827":27623,"53828":27685,"53829":28026,"53830":28003,"53831":28004,"53832":28022,"53833":27917,"53834":28001,"53835":28050,"53836":27992,"53837":28002,"53838":28013,"53839":28015,"53840":28049,"53841":28045,"53842":28143,"53843":28031,"53844":28038,"53845":27998,"53846":28007,"53847":28000,"53848":28055,"53849":28016,"53850":28028,"53851":27999,"53852":28034,"53853":28056,"53854":27951,"53855":28008,"53856":28043,"53857":28030,"53858":28032,"53859":28036,"53860":27926,"53861":28035,"53862":28027,"53863":28029,"53864":28021,"53865":28048,"53866":28892,"53867":28883,"53868":28881,"53869":28893,"53870":28875,"53871":32569,"53872":28898,"53873":28887,"53874":28882,"53875":28894,"53876":28896,"53877":28884,"53878":28877,"53879":28869,"53880":28870,"53881":28871,"53882":28890,"53883":28878,"53884":28897,"53885":29250,"53886":29304,"53921":29303,"53922":29302,"53923":29440,"53924":29434,"53925":29428,"53926":29438,"53927":29430,"53928":29427,"53929":29435,"53930":29441,"53931":29651,"53932":29657,"53933":29669,"53934":29654,"53935":29628,"53936":29671,"53937":29667,"53938":29673,"53939":29660,"53940":29650,"53941":29659,"53942":29652,"53943":29661,"53944":29658,"53945":29655,"53946":29656,"53947":29672,"53948":29918,"53949":29919,"53950":29940,"53951":29941,"53952":29985,"53953":30043,"53954":30047,"53955":30128,"53956":30145,"53957":30139,"53958":30148,"53959":30144,"53960":30143,"53961":30134,"53962":30138,"53963":30346,"53964":30409,"53965":30493,"53966":30491,"53967":30480,"53968":30483,"53969":30482,"53970":30499,"53971":30481,"53972":30485,"53973":30489,"53974":30490,"53975":30498,"53976":30503,"53977":30755,"53978":30764,"53979":30754,"53980":30773,"53981":30767,"53982":30760,"53983":30766,"53984":30763,"53985":30753,"53986":30761,"53987":30771,"53988":30762,"53989":30769,"53990":31060,"53991":31067,"53992":31055,"53993":31068,"53994":31059,"53995":31058,"53996":31057,"53997":31211,"53998":31212,"53999":31200,"54000":31214,"54001":31213,"54002":31210,"54003":31196,"54004":31198,"54005":31197,"54006":31366,"54007":31369,"54008":31365,"54009":31371,"54010":31372,"54011":31370,"54012":31367,"54013":31448,"54014":31504,"54080":31492,"54081":31507,"54082":31493,"54083":31503,"54084":31496,"54085":31498,"54086":31502,"54087":31497,"54088":31506,"54089":31876,"54090":31889,"54091":31882,"54092":31884,"54093":31880,"54094":31885,"54095":31877,"54096":32030,"54097":32029,"54098":32017,"54099":32014,"54100":32024,"54101":32022,"54102":32019,"54103":32031,"54104":32018,"54105":32015,"54106":32012,"54107":32604,"54108":32609,"54109":32606,"54110":32608,"54111":32605,"54112":32603,"54113":32662,"54114":32658,"54115":32707,"54116":32706,"54117":32704,"54118":32790,"54119":32830,"54120":32825,"54121":33018,"54122":33010,"54123":33017,"54124":33013,"54125":33025,"54126":33019,"54127":33024,"54128":33281,"54129":33327,"54130":33317,"54131":33587,"54132":33581,"54133":33604,"54134":33561,"54135":33617,"54136":33573,"54137":33622,"54138":33599,"54139":33601,"54140":33574,"54141":33564,"54142":33570,"54177":33602,"54178":33614,"54179":33563,"54180":33578,"54181":33544,"54182":33596,"54183":33613,"54184":33558,"54185":33572,"54186":33568,"54187":33591,"54188":33583,"54189":33577,"54190":33607,"54191":33605,"54192":33612,"54193":33619,"54194":33566,"54195":33580,"54196":33611,"54197":33575,"54198":33608,"54199":34387,"54200":34386,"54201":34466,"54202":34472,"54203":34454,"54204":34445,"54205":34449,"54206":34462,"54207":34439,"54208":34455,"54209":34438,"54210":34443,"54211":34458,"54212":34437,"54213":34469,"54214":34457,"54215":34465,"54216":34471,"54217":34453,"54218":34456,"54219":34446,"54220":34461,"54221":34448,"54222":34452,"54223":34883,"54224":34884,"54225":34925,"54226":34933,"54227":34934,"54228":34930,"54229":34944,"54230":34929,"54231":34943,"54232":34927,"54233":34947,"54234":34942,"54235":34932,"54236":34940,"54237":35346,"54238":35911,"54239":35927,"54240":35963,"54241":36004,"54242":36003,"54243":36214,"54244":36216,"54245":36277,"54246":36279,"54247":36278,"54248":36561,"54249":36563,"54250":36862,"54251":36853,"54252":36866,"54253":36863,"54254":36859,"54255":36868,"54256":36860,"54257":36854,"54258":37078,"54259":37088,"54260":37081,"54261":37082,"54262":37091,"54263":37087,"54264":37093,"54265":37080,"54266":37083,"54267":37079,"54268":37084,"54269":37092,"54270":37200,"54336":37198,"54337":37199,"54338":37333,"54339":37346,"54340":37338,"54341":38492,"54342":38495,"54343":38588,"54344":39139,"54345":39647,"54346":39727,"54347":20095,"54348":20592,"54349":20586,"54350":20577,"54351":20574,"54352":20576,"54353":20563,"54354":20555,"54355":20573,"54356":20594,"54357":20552,"54358":20557,"54359":20545,"54360":20571,"54361":20554,"54362":20578,"54363":20501,"54364":20549,"54365":20575,"54366":20585,"54367":20587,"54368":20579,"54369":20580,"54370":20550,"54371":20544,"54372":20590,"54373":20595,"54374":20567,"54375":20561,"54376":20944,"54377":21099,"54378":21101,"54379":21100,"54380":21102,"54381":21206,"54382":21203,"54383":21293,"54384":21404,"54385":21877,"54386":21878,"54387":21820,"54388":21837,"54389":21840,"54390":21812,"54391":21802,"54392":21841,"54393":21858,"54394":21814,"54395":21813,"54396":21808,"54397":21842,"54398":21829,"54433":21772,"54434":21810,"54435":21861,"54436":21838,"54437":21817,"54438":21832,"54439":21805,"54440":21819,"54441":21824,"54442":21835,"54443":22282,"54444":22279,"54445":22523,"54446":22548,"54447":22498,"54448":22518,"54449":22492,"54450":22516,"54451":22528,"54452":22509,"54453":22525,"54454":22536,"54455":22520,"54456":22539,"54457":22515,"54458":22479,"54459":22535,"54460":22510,"54461":22499,"54462":22514,"54463":22501,"54464":22508,"54465":22497,"54466":22542,"54467":22524,"54468":22544,"54469":22503,"54470":22529,"54471":22540,"54472":22513,"54473":22505,"54474":22512,"54475":22541,"54476":22532,"54477":22876,"54478":23136,"54479":23128,"54480":23125,"54481":23143,"54482":23134,"54483":23096,"54484":23093,"54485":23149,"54486":23120,"54487":23135,"54488":23141,"54489":23148,"54490":23123,"54491":23140,"54492":23127,"54493":23107,"54494":23133,"54495":23122,"54496":23108,"54497":23131,"54498":23112,"54499":23182,"54500":23102,"54501":23117,"54502":23097,"54503":23116,"54504":23152,"54505":23145,"54506":23111,"54507":23121,"54508":23126,"54509":23106,"54510":23132,"54511":23410,"54512":23406,"54513":23489,"54514":23488,"54515":23641,"54516":23838,"54517":23819,"54518":23837,"54519":23834,"54520":23840,"54521":23820,"54522":23848,"54523":23821,"54524":23846,"54525":23845,"54526":23823,"54592":23856,"54593":23826,"54594":23843,"54595":23839,"54596":23854,"54597":24126,"54598":24116,"54599":24241,"54600":24244,"54601":24249,"54602":24242,"54603":24243,"54604":24374,"54605":24376,"54606":24475,"54607":24470,"54608":24479,"54609":24714,"54610":24720,"54611":24710,"54612":24766,"54613":24752,"54614":24762,"54615":24787,"54616":24788,"54617":24783,"54618":24804,"54619":24793,"54620":24797,"54621":24776,"54622":24753,"54623":24795,"54624":24759,"54625":24778,"54626":24767,"54627":24771,"54628":24781,"54629":24768,"54630":25394,"54631":25445,"54632":25482,"54633":25474,"54634":25469,"54635":25533,"54636":25502,"54637":25517,"54638":25501,"54639":25495,"54640":25515,"54641":25486,"54642":25455,"54643":25479,"54644":25488,"54645":25454,"54646":25519,"54647":25461,"54648":25500,"54649":25453,"54650":25518,"54651":25468,"54652":25508,"54653":25403,"54654":25503,"54689":25464,"54690":25477,"54691":25473,"54692":25489,"54693":25485,"54694":25456,"54695":25939,"54696":26061,"54697":26213,"54698":26209,"54699":26203,"54700":26201,"54701":26204,"54702":26210,"54703":26392,"54704":26745,"54705":26759,"54706":26768,"54707":26780,"54708":26733,"54709":26734,"54710":26798,"54711":26795,"54712":26966,"54713":26735,"54714":26787,"54715":26796,"54716":26793,"54717":26741,"54718":26740,"54719":26802,"54720":26767,"54721":26743,"54722":26770,"54723":26748,"54724":26731,"54725":26738,"54726":26794,"54727":26752,"54728":26737,"54729":26750,"54730":26779,"54731":26774,"54732":26763,"54733":26784,"54734":26761,"54735":26788,"54736":26744,"54737":26747,"54738":26769,"54739":26764,"54740":26762,"54741":26749,"54742":27446,"54743":27443,"54744":27447,"54745":27448,"54746":27537,"54747":27535,"54748":27533,"54749":27534,"54750":27532,"54751":27690,"54752":28096,"54753":28075,"54754":28084,"54755":28083,"54756":28276,"54757":28076,"54758":28137,"54759":28130,"54760":28087,"54761":28150,"54762":28116,"54763":28160,"54764":28104,"54765":28128,"54766":28127,"54767":28118,"54768":28094,"54769":28133,"54770":28124,"54771":28125,"54772":28123,"54773":28148,"54774":28106,"54775":28093,"54776":28141,"54777":28144,"54778":28090,"54779":28117,"54780":28098,"54781":28111,"54782":28105,"54848":28112,"54849":28146,"54850":28115,"54851":28157,"54852":28119,"54853":28109,"54854":28131,"54855":28091,"54856":28922,"54857":28941,"54858":28919,"54859":28951,"54860":28916,"54861":28940,"54862":28912,"54863":28932,"54864":28915,"54865":28944,"54866":28924,"54867":28927,"54868":28934,"54869":28947,"54870":28928,"54871":28920,"54872":28918,"54873":28939,"54874":28930,"54875":28942,"54876":29310,"54877":29307,"54878":29308,"54879":29311,"54880":29469,"54881":29463,"54882":29447,"54883":29457,"54884":29464,"54885":29450,"54886":29448,"54887":29439,"54888":29455,"54889":29470,"54890":29576,"54891":29686,"54892":29688,"54893":29685,"54894":29700,"54895":29697,"54896":29693,"54897":29703,"54898":29696,"54899":29690,"54900":29692,"54901":29695,"54902":29708,"54903":29707,"54904":29684,"54905":29704,"54906":30052,"54907":30051,"54908":30158,"54909":30162,"54910":30159,"54945":30155,"54946":30156,"54947":30161,"54948":30160,"54949":30351,"54950":30345,"54951":30419,"54952":30521,"54953":30511,"54954":30509,"54955":30513,"54956":30514,"54957":30516,"54958":30515,"54959":30525,"54960":30501,"54961":30523,"54962":30517,"54963":30792,"54964":30802,"54965":30793,"54966":30797,"54967":30794,"54968":30796,"54969":30758,"54970":30789,"54971":30800,"54972":31076,"54973":31079,"54974":31081,"54975":31082,"54976":31075,"54977":31083,"54978":31073,"54979":31163,"54980":31226,"54981":31224,"54982":31222,"54983":31223,"54984":31375,"54985":31380,"54986":31376,"54987":31541,"54988":31559,"54989":31540,"54990":31525,"54991":31536,"54992":31522,"54993":31524,"54994":31539,"54995":31512,"54996":31530,"54997":31517,"54998":31537,"54999":31531,"55000":31533,"55001":31535,"55002":31538,"55003":31544,"55004":31514,"55005":31523,"55006":31892,"55007":31896,"55008":31894,"55009":31907,"55010":32053,"55011":32061,"55012":32056,"55013":32054,"55014":32058,"55015":32069,"55016":32044,"55017":32041,"55018":32065,"55019":32071,"55020":32062,"55021":32063,"55022":32074,"55023":32059,"55024":32040,"55025":32611,"55026":32661,"55027":32668,"55028":32669,"55029":32667,"55030":32714,"55031":32715,"55032":32717,"55033":32720,"55034":32721,"55035":32711,"55036":32719,"55037":32713,"55038":32799,"55104":32798,"55105":32795,"55106":32839,"55107":32835,"55108":32840,"55109":33048,"55110":33061,"55111":33049,"55112":33051,"55113":33069,"55114":33055,"55115":33068,"55116":33054,"55117":33057,"55118":33045,"55119":33063,"55120":33053,"55121":33058,"55122":33297,"55123":33336,"55124":33331,"55125":33338,"55126":33332,"55127":33330,"55128":33396,"55129":33680,"55130":33699,"55131":33704,"55132":33677,"55133":33658,"55134":33651,"55135":33700,"55136":33652,"55137":33679,"55138":33665,"55139":33685,"55140":33689,"55141":33653,"55142":33684,"55143":33705,"55144":33661,"55145":33667,"55146":33676,"55147":33693,"55148":33691,"55149":33706,"55150":33675,"55151":33662,"55152":33701,"55153":33711,"55154":33672,"55155":33687,"55156":33712,"55157":33663,"55158":33702,"55159":33671,"55160":33710,"55161":33654,"55162":33690,"55163":34393,"55164":34390,"55165":34495,"55166":34487,"55201":34498,"55202":34497,"55203":34501,"55204":34490,"55205":34480,"55206":34504,"55207":34489,"55208":34483,"55209":34488,"55210":34508,"55211":34484,"55212":34491,"55213":34492,"55214":34499,"55215":34493,"55216":34494,"55217":34898,"55218":34953,"55219":34965,"55220":34984,"55221":34978,"55222":34986,"55223":34970,"55224":34961,"55225":34977,"55226":34975,"55227":34968,"55228":34983,"55229":34969,"55230":34971,"55231":34967,"55232":34980,"55233":34988,"55234":34956,"55235":34963,"55236":34958,"55237":35202,"55238":35286,"55239":35289,"55240":35285,"55241":35376,"55242":35367,"55243":35372,"55244":35358,"55245":35897,"55246":35899,"55247":35932,"55248":35933,"55249":35965,"55250":36005,"55251":36221,"55252":36219,"55253":36217,"55254":36284,"55255":36290,"55256":36281,"55257":36287,"55258":36289,"55259":36568,"55260":36574,"55261":36573,"55262":36572,"55263":36567,"55264":36576,"55265":36577,"55266":36900,"55267":36875,"55268":36881,"55269":36892,"55270":36876,"55271":36897,"55272":37103,"55273":37098,"55274":37104,"55275":37108,"55276":37106,"55277":37107,"55278":37076,"55279":37099,"55280":37100,"55281":37097,"55282":37206,"55283":37208,"55284":37210,"55285":37203,"55286":37205,"55287":37356,"55288":37364,"55289":37361,"55290":37363,"55291":37368,"55292":37348,"55293":37369,"55294":37354,"55360":37355,"55361":37367,"55362":37352,"55363":37358,"55364":38266,"55365":38278,"55366":38280,"55367":38524,"55368":38509,"55369":38507,"55370":38513,"55371":38511,"55372":38591,"55373":38762,"55374":38916,"55375":39141,"55376":39319,"55377":20635,"55378":20629,"55379":20628,"55380":20638,"55381":20619,"55382":20643,"55383":20611,"55384":20620,"55385":20622,"55386":20637,"55387":20584,"55388":20636,"55389":20626,"55390":20610,"55391":20615,"55392":20831,"55393":20948,"55394":21266,"55395":21265,"55396":21412,"55397":21415,"55398":21905,"55399":21928,"55400":21925,"55401":21933,"55402":21879,"55403":22085,"55404":21922,"55405":21907,"55406":21896,"55407":21903,"55408":21941,"55409":21889,"55410":21923,"55411":21906,"55412":21924,"55413":21885,"55414":21900,"55415":21926,"55416":21887,"55417":21909,"55418":21921,"55419":21902,"55420":22284,"55421":22569,"55422":22583,"55457":22553,"55458":22558,"55459":22567,"55460":22563,"55461":22568,"55462":22517,"55463":22600,"55464":22565,"55465":22556,"55466":22555,"55467":22579,"55468":22591,"55469":22582,"55470":22574,"55471":22585,"55472":22584,"55473":22573,"55474":22572,"55475":22587,"55476":22881,"55477":23215,"55478":23188,"55479":23199,"55480":23162,"55481":23202,"55482":23198,"55483":23160,"55484":23206,"55485":23164,"55486":23205,"55487":23212,"55488":23189,"55489":23214,"55490":23095,"55491":23172,"55492":23178,"55493":23191,"55494":23171,"55495":23179,"55496":23209,"55497":23163,"55498":23165,"55499":23180,"55500":23196,"55501":23183,"55502":23187,"55503":23197,"55504":23530,"55505":23501,"55506":23499,"55507":23508,"55508":23505,"55509":23498,"55510":23502,"55511":23564,"55512":23600,"55513":23863,"55514":23875,"55515":23915,"55516":23873,"55517":23883,"55518":23871,"55519":23861,"55520":23889,"55521":23886,"55522":23893,"55523":23859,"55524":23866,"55525":23890,"55526":23869,"55527":23857,"55528":23897,"55529":23874,"55530":23865,"55531":23881,"55532":23864,"55533":23868,"55534":23858,"55535":23862,"55536":23872,"55537":23877,"55538":24132,"55539":24129,"55540":24408,"55541":24486,"55542":24485,"55543":24491,"55544":24777,"55545":24761,"55546":24780,"55547":24802,"55548":24782,"55549":24772,"55550":24852,"55616":24818,"55617":24842,"55618":24854,"55619":24837,"55620":24821,"55621":24851,"55622":24824,"55623":24828,"55624":24830,"55625":24769,"55626":24835,"55627":24856,"55628":24861,"55629":24848,"55630":24831,"55631":24836,"55632":24843,"55633":25162,"55634":25492,"55635":25521,"55636":25520,"55637":25550,"55638":25573,"55639":25576,"55640":25583,"55641":25539,"55642":25757,"55643":25587,"55644":25546,"55645":25568,"55646":25590,"55647":25557,"55648":25586,"55649":25589,"55650":25697,"55651":25567,"55652":25534,"55653":25565,"55654":25564,"55655":25540,"55656":25560,"55657":25555,"55658":25538,"55659":25543,"55660":25548,"55661":25547,"55662":25544,"55663":25584,"55664":25559,"55665":25561,"55666":25906,"55667":25959,"55668":25962,"55669":25956,"55670":25948,"55671":25960,"55672":25957,"55673":25996,"55674":26013,"55675":26014,"55676":26030,"55677":26064,"55678":26066,"55713":26236,"55714":26220,"55715":26235,"55716":26240,"55717":26225,"55718":26233,"55719":26218,"55720":26226,"55721":26369,"55722":26892,"55723":26835,"55724":26884,"55725":26844,"55726":26922,"55727":26860,"55728":26858,"55729":26865,"55730":26895,"55731":26838,"55732":26871,"55733":26859,"55734":26852,"55735":26870,"55736":26899,"55737":26896,"55738":26867,"55739":26849,"55740":26887,"55741":26828,"55742":26888,"55743":26992,"55744":26804,"55745":26897,"55746":26863,"55747":26822,"55748":26900,"55749":26872,"55750":26832,"55751":26877,"55752":26876,"55753":26856,"55754":26891,"55755":26890,"55756":26903,"55757":26830,"55758":26824,"55759":26845,"55760":26846,"55761":26854,"55762":26868,"55763":26833,"55764":26886,"55765":26836,"55766":26857,"55767":26901,"55768":26917,"55769":26823,"55770":27449,"55771":27451,"55772":27455,"55773":27452,"55774":27540,"55775":27543,"55776":27545,"55777":27541,"55778":27581,"55779":27632,"55780":27634,"55781":27635,"55782":27696,"55783":28156,"55784":28230,"55785":28231,"55786":28191,"55787":28233,"55788":28296,"55789":28220,"55790":28221,"55791":28229,"55792":28258,"55793":28203,"55794":28223,"55795":28225,"55796":28253,"55797":28275,"55798":28188,"55799":28211,"55800":28235,"55801":28224,"55802":28241,"55803":28219,"55804":28163,"55805":28206,"55806":28254,"55872":28264,"55873":28252,"55874":28257,"55875":28209,"55876":28200,"55877":28256,"55878":28273,"55879":28267,"55880":28217,"55881":28194,"55882":28208,"55883":28243,"55884":28261,"55885":28199,"55886":28280,"55887":28260,"55888":28279,"55889":28245,"55890":28281,"55891":28242,"55892":28262,"55893":28213,"55894":28214,"55895":28250,"55896":28960,"55897":28958,"55898":28975,"55899":28923,"55900":28974,"55901":28977,"55902":28963,"55903":28965,"55904":28962,"55905":28978,"55906":28959,"55907":28968,"55908":28986,"55909":28955,"55910":29259,"55911":29274,"55912":29320,"55913":29321,"55914":29318,"55915":29317,"55916":29323,"55917":29458,"55918":29451,"55919":29488,"55920":29474,"55921":29489,"55922":29491,"55923":29479,"55924":29490,"55925":29485,"55926":29478,"55927":29475,"55928":29493,"55929":29452,"55930":29742,"55931":29740,"55932":29744,"55933":29739,"55934":29718,"55969":29722,"55970":29729,"55971":29741,"55972":29745,"55973":29732,"55974":29731,"55975":29725,"55976":29737,"55977":29728,"55978":29746,"55979":29947,"55980":29999,"55981":30063,"55982":30060,"55983":30183,"55984":30170,"55985":30177,"55986":30182,"55987":30173,"55988":30175,"55989":30180,"55990":30167,"55991":30357,"55992":30354,"55993":30426,"55994":30534,"55995":30535,"55996":30532,"55997":30541,"55998":30533,"55999":30538,"56000":30542,"56001":30539,"56002":30540,"56003":30686,"56004":30700,"56005":30816,"56006":30820,"56007":30821,"56008":30812,"56009":30829,"56010":30833,"56011":30826,"56012":30830,"56013":30832,"56014":30825,"56015":30824,"56016":30814,"56017":30818,"56018":31092,"56019":31091,"56020":31090,"56021":31088,"56022":31234,"56023":31242,"56024":31235,"56025":31244,"56026":31236,"56027":31385,"56028":31462,"56029":31460,"56030":31562,"56031":31547,"56032":31556,"56033":31560,"56034":31564,"56035":31566,"56036":31552,"56037":31576,"56038":31557,"56039":31906,"56040":31902,"56041":31912,"56042":31905,"56043":32088,"56044":32111,"56045":32099,"56046":32083,"56047":32086,"56048":32103,"56049":32106,"56050":32079,"56051":32109,"56052":32092,"56053":32107,"56054":32082,"56055":32084,"56056":32105,"56057":32081,"56058":32095,"56059":32078,"56060":32574,"56061":32575,"56062":32613,"56128":32614,"56129":32674,"56130":32672,"56131":32673,"56132":32727,"56133":32849,"56134":32847,"56135":32848,"56136":33022,"56137":32980,"56138":33091,"56139":33098,"56140":33106,"56141":33103,"56142":33095,"56143":33085,"56144":33101,"56145":33082,"56146":33254,"56147":33262,"56148":33271,"56149":33272,"56150":33273,"56151":33284,"56152":33340,"56153":33341,"56154":33343,"56155":33397,"56156":33595,"56157":33743,"56158":33785,"56159":33827,"56160":33728,"56161":33768,"56162":33810,"56163":33767,"56164":33764,"56165":33788,"56166":33782,"56167":33808,"56168":33734,"56169":33736,"56170":33771,"56171":33763,"56172":33727,"56173":33793,"56174":33757,"56175":33765,"56176":33752,"56177":33791,"56178":33761,"56179":33739,"56180":33742,"56181":33750,"56182":33781,"56183":33737,"56184":33801,"56185":33807,"56186":33758,"56187":33809,"56188":33798,"56189":33730,"56190":33779,"56225":33749,"56226":33786,"56227":33735,"56228":33745,"56229":33770,"56230":33811,"56231":33731,"56232":33772,"56233":33774,"56234":33732,"56235":33787,"56236":33751,"56237":33762,"56238":33819,"56239":33755,"56240":33790,"56241":34520,"56242":34530,"56243":34534,"56244":34515,"56245":34531,"56246":34522,"56247":34538,"56248":34525,"56249":34539,"56250":34524,"56251":34540,"56252":34537,"56253":34519,"56254":34536,"56255":34513,"56256":34888,"56257":34902,"56258":34901,"56259":35002,"56260":35031,"56261":35001,"56262":35000,"56263":35008,"56264":35006,"56265":34998,"56266":35004,"56267":34999,"56268":35005,"56269":34994,"56270":35073,"56271":35017,"56272":35221,"56273":35224,"56274":35223,"56275":35293,"56276":35290,"56277":35291,"56278":35406,"56279":35405,"56280":35385,"56281":35417,"56282":35392,"56283":35415,"56284":35416,"56285":35396,"56286":35397,"56287":35410,"56288":35400,"56289":35409,"56290":35402,"56291":35404,"56292":35407,"56293":35935,"56294":35969,"56295":35968,"56296":36026,"56297":36030,"56298":36016,"56299":36025,"56300":36021,"56301":36228,"56302":36224,"56303":36233,"56304":36312,"56305":36307,"56306":36301,"56307":36295,"56308":36310,"56309":36316,"56310":36303,"56311":36309,"56312":36313,"56313":36296,"56314":36311,"56315":36293,"56316":36591,"56317":36599,"56318":36602,"56384":36601,"56385":36582,"56386":36590,"56387":36581,"56388":36597,"56389":36583,"56390":36584,"56391":36598,"56392":36587,"56393":36593,"56394":36588,"56395":36596,"56396":36585,"56397":36909,"56398":36916,"56399":36911,"56400":37126,"56401":37164,"56402":37124,"56403":37119,"56404":37116,"56405":37128,"56406":37113,"56407":37115,"56408":37121,"56409":37120,"56410":37127,"56411":37125,"56412":37123,"56413":37217,"56414":37220,"56415":37215,"56416":37218,"56417":37216,"56418":37377,"56419":37386,"56420":37413,"56421":37379,"56422":37402,"56423":37414,"56424":37391,"56425":37388,"56426":37376,"56427":37394,"56428":37375,"56429":37373,"56430":37382,"56431":37380,"56432":37415,"56433":37378,"56434":37404,"56435":37412,"56436":37401,"56437":37399,"56438":37381,"56439":37398,"56440":38267,"56441":38285,"56442":38284,"56443":38288,"56444":38535,"56445":38526,"56446":38536,"56481":38537,"56482":38531,"56483":38528,"56484":38594,"56485":38600,"56486":38595,"56487":38641,"56488":38640,"56489":38764,"56490":38768,"56491":38766,"56492":38919,"56493":39081,"56494":39147,"56495":40166,"56496":40697,"56497":20099,"56498":20100,"56499":20150,"56500":20669,"56501":20671,"56502":20678,"56503":20654,"56504":20676,"56505":20682,"56506":20660,"56507":20680,"56508":20674,"56509":20656,"56510":20673,"56511":20666,"56512":20657,"56513":20683,"56514":20681,"56515":20662,"56516":20664,"56517":20951,"56518":21114,"56519":21112,"56520":21115,"56521":21116,"56522":21955,"56523":21979,"56524":21964,"56525":21968,"56526":21963,"56527":21962,"56528":21981,"56529":21952,"56530":21972,"56531":21956,"56532":21993,"56533":21951,"56534":21970,"56535":21901,"56536":21967,"56537":21973,"56538":21986,"56539":21974,"56540":21960,"56541":22002,"56542":21965,"56543":21977,"56544":21954,"56545":22292,"56546":22611,"56547":22632,"56548":22628,"56549":22607,"56550":22605,"56551":22601,"56552":22639,"56553":22613,"56554":22606,"56555":22621,"56556":22617,"56557":22629,"56558":22619,"56559":22589,"56560":22627,"56561":22641,"56562":22780,"56563":23239,"56564":23236,"56565":23243,"56566":23226,"56567":23224,"56568":23217,"56569":23221,"56570":23216,"56571":23231,"56572":23240,"56573":23227,"56574":23238,"56640":23223,"56641":23232,"56642":23242,"56643":23220,"56644":23222,"56645":23245,"56646":23225,"56647":23184,"56648":23510,"56649":23512,"56650":23513,"56651":23583,"56652":23603,"56653":23921,"56654":23907,"56655":23882,"56656":23909,"56657":23922,"56658":23916,"56659":23902,"56660":23912,"56661":23911,"56662":23906,"56663":24048,"56664":24143,"56665":24142,"56666":24138,"56667":24141,"56668":24139,"56669":24261,"56670":24268,"56671":24262,"56672":24267,"56673":24263,"56674":24384,"56675":24495,"56676":24493,"56677":24823,"56678":24905,"56679":24906,"56680":24875,"56681":24901,"56682":24886,"56683":24882,"56684":24878,"56685":24902,"56686":24879,"56687":24911,"56688":24873,"56689":24896,"56690":25120,"56691":37224,"56692":25123,"56693":25125,"56694":25124,"56695":25541,"56696":25585,"56697":25579,"56698":25616,"56699":25618,"56700":25609,"56701":25632,"56702":25636,"56737":25651,"56738":25667,"56739":25631,"56740":25621,"56741":25624,"56742":25657,"56743":25655,"56744":25634,"56745":25635,"56746":25612,"56747":25638,"56748":25648,"56749":25640,"56750":25665,"56751":25653,"56752":25647,"56753":25610,"56754":25626,"56755":25664,"56756":25637,"56757":25639,"56758":25611,"56759":25575,"56760":25627,"56761":25646,"56762":25633,"56763":25614,"56764":25967,"56765":26002,"56766":26067,"56767":26246,"56768":26252,"56769":26261,"56770":26256,"56771":26251,"56772":26250,"56773":26265,"56774":26260,"56775":26232,"56776":26400,"56777":26982,"56778":26975,"56779":26936,"56780":26958,"56781":26978,"56782":26993,"56783":26943,"56784":26949,"56785":26986,"56786":26937,"56787":26946,"56788":26967,"56789":26969,"56790":27002,"56791":26952,"56792":26953,"56793":26933,"56794":26988,"56795":26931,"56796":26941,"56797":26981,"56798":26864,"56799":27000,"56800":26932,"56801":26985,"56802":26944,"56803":26991,"56804":26948,"56805":26998,"56806":26968,"56807":26945,"56808":26996,"56809":26956,"56810":26939,"56811":26955,"56812":26935,"56813":26972,"56814":26959,"56815":26961,"56816":26930,"56817":26962,"56818":26927,"56819":27003,"56820":26940,"56821":27462,"56822":27461,"56823":27459,"56824":27458,"56825":27464,"56826":27457,"56827":27547,"56828":64013,"56829":27643,"56830":27644,"56896":27641,"56897":27639,"56898":27640,"56899":28315,"56900":28374,"56901":28360,"56902":28303,"56903":28352,"56904":28319,"56905":28307,"56906":28308,"56907":28320,"56908":28337,"56909":28345,"56910":28358,"56911":28370,"56912":28349,"56913":28353,"56914":28318,"56915":28361,"56916":28343,"56917":28336,"56918":28365,"56919":28326,"56920":28367,"56921":28338,"56922":28350,"56923":28355,"56924":28380,"56925":28376,"56926":28313,"56927":28306,"56928":28302,"56929":28301,"56930":28324,"56931":28321,"56932":28351,"56933":28339,"56934":28368,"56935":28362,"56936":28311,"56937":28334,"56938":28323,"56939":28999,"56940":29012,"56941":29010,"56942":29027,"56943":29024,"56944":28993,"56945":29021,"56946":29026,"56947":29042,"56948":29048,"56949":29034,"56950":29025,"56951":28994,"56952":29016,"56953":28995,"56954":29003,"56955":29040,"56956":29023,"56957":29008,"56958":29011,"56993":28996,"56994":29005,"56995":29018,"56996":29263,"56997":29325,"56998":29324,"56999":29329,"57000":29328,"57001":29326,"57002":29500,"57003":29506,"57004":29499,"57005":29498,"57006":29504,"57007":29514,"57008":29513,"57009":29764,"57010":29770,"57011":29771,"57012":29778,"57013":29777,"57014":29783,"57015":29760,"57016":29775,"57017":29776,"57018":29774,"57019":29762,"57020":29766,"57021":29773,"57022":29780,"57023":29921,"57024":29951,"57025":29950,"57026":29949,"57027":29981,"57028":30073,"57029":30071,"57030":27011,"57031":30191,"57032":30223,"57033":30211,"57034":30199,"57035":30206,"57036":30204,"57037":30201,"57038":30200,"57039":30224,"57040":30203,"57041":30198,"57042":30189,"57043":30197,"57044":30205,"57045":30361,"57046":30389,"57047":30429,"57048":30549,"57049":30559,"57050":30560,"57051":30546,"57052":30550,"57053":30554,"57054":30569,"57055":30567,"57056":30548,"57057":30553,"57058":30573,"57059":30688,"57060":30855,"57061":30874,"57062":30868,"57063":30863,"57064":30852,"57065":30869,"57066":30853,"57067":30854,"57068":30881,"57069":30851,"57070":30841,"57071":30873,"57072":30848,"57073":30870,"57074":30843,"57075":31100,"57076":31106,"57077":31101,"57078":31097,"57079":31249,"57080":31256,"57081":31257,"57082":31250,"57083":31255,"57084":31253,"57085":31266,"57086":31251,"57152":31259,"57153":31248,"57154":31395,"57155":31394,"57156":31390,"57157":31467,"57158":31590,"57159":31588,"57160":31597,"57161":31604,"57162":31593,"57163":31602,"57164":31589,"57165":31603,"57166":31601,"57167":31600,"57168":31585,"57169":31608,"57170":31606,"57171":31587,"57172":31922,"57173":31924,"57174":31919,"57175":32136,"57176":32134,"57177":32128,"57178":32141,"57179":32127,"57180":32133,"57181":32122,"57182":32142,"57183":32123,"57184":32131,"57185":32124,"57186":32140,"57187":32148,"57188":32132,"57189":32125,"57190":32146,"57191":32621,"57192":32619,"57193":32615,"57194":32616,"57195":32620,"57196":32678,"57197":32677,"57198":32679,"57199":32731,"57200":32732,"57201":32801,"57202":33124,"57203":33120,"57204":33143,"57205":33116,"57206":33129,"57207":33115,"57208":33122,"57209":33138,"57210":26401,"57211":33118,"57212":33142,"57213":33127,"57214":33135,"57249":33092,"57250":33121,"57251":33309,"57252":33353,"57253":33348,"57254":33344,"57255":33346,"57256":33349,"57257":34033,"57258":33855,"57259":33878,"57260":33910,"57261":33913,"57262":33935,"57263":33933,"57264":33893,"57265":33873,"57266":33856,"57267":33926,"57268":33895,"57269":33840,"57270":33869,"57271":33917,"57272":33882,"57273":33881,"57274":33908,"57275":33907,"57276":33885,"57277":34055,"57278":33886,"57279":33847,"57280":33850,"57281":33844,"57282":33914,"57283":33859,"57284":33912,"57285":33842,"57286":33861,"57287":33833,"57288":33753,"57289":33867,"57290":33839,"57291":33858,"57292":33837,"57293":33887,"57294":33904,"57295":33849,"57296":33870,"57297":33868,"57298":33874,"57299":33903,"57300":33989,"57301":33934,"57302":33851,"57303":33863,"57304":33846,"57305":33843,"57306":33896,"57307":33918,"57308":33860,"57309":33835,"57310":33888,"57311":33876,"57312":33902,"57313":33872,"57314":34571,"57315":34564,"57316":34551,"57317":34572,"57318":34554,"57319":34518,"57320":34549,"57321":34637,"57322":34552,"57323":34574,"57324":34569,"57325":34561,"57326":34550,"57327":34573,"57328":34565,"57329":35030,"57330":35019,"57331":35021,"57332":35022,"57333":35038,"57334":35035,"57335":35034,"57336":35020,"57337":35024,"57338":35205,"57339":35227,"57340":35295,"57341":35301,"57342":35300,"57408":35297,"57409":35296,"57410":35298,"57411":35292,"57412":35302,"57413":35446,"57414":35462,"57415":35455,"57416":35425,"57417":35391,"57418":35447,"57419":35458,"57420":35460,"57421":35445,"57422":35459,"57423":35457,"57424":35444,"57425":35450,"57426":35900,"57427":35915,"57428":35914,"57429":35941,"57430":35940,"57431":35942,"57432":35974,"57433":35972,"57434":35973,"57435":36044,"57436":36200,"57437":36201,"57438":36241,"57439":36236,"57440":36238,"57441":36239,"57442":36237,"57443":36243,"57444":36244,"57445":36240,"57446":36242,"57447":36336,"57448":36320,"57449":36332,"57450":36337,"57451":36334,"57452":36304,"57453":36329,"57454":36323,"57455":36322,"57456":36327,"57457":36338,"57458":36331,"57459":36340,"57460":36614,"57461":36607,"57462":36609,"57463":36608,"57464":36613,"57465":36615,"57466":36616,"57467":36610,"57468":36619,"57469":36946,"57470":36927,"57505":36932,"57506":36937,"57507":36925,"57508":37136,"57509":37133,"57510":37135,"57511":37137,"57512":37142,"57513":37140,"57514":37131,"57515":37134,"57516":37230,"57517":37231,"57518":37448,"57519":37458,"57520":37424,"57521":37434,"57522":37478,"57523":37427,"57524":37477,"57525":37470,"57526":37507,"57527":37422,"57528":37450,"57529":37446,"57530":37485,"57531":37484,"57532":37455,"57533":37472,"57534":37479,"57535":37487,"57536":37430,"57537":37473,"57538":37488,"57539":37425,"57540":37460,"57541":37475,"57542":37456,"57543":37490,"57544":37454,"57545":37459,"57546":37452,"57547":37462,"57548":37426,"57549":38303,"57550":38300,"57551":38302,"57552":38299,"57553":38546,"57554":38547,"57555":38545,"57556":38551,"57557":38606,"57558":38650,"57559":38653,"57560":38648,"57561":38645,"57562":38771,"57563":38775,"57564":38776,"57565":38770,"57566":38927,"57567":38925,"57568":38926,"57569":39084,"57570":39158,"57571":39161,"57572":39343,"57573":39346,"57574":39344,"57575":39349,"57576":39597,"57577":39595,"57578":39771,"57579":40170,"57580":40173,"57581":40167,"57582":40576,"57583":40701,"57584":20710,"57585":20692,"57586":20695,"57587":20712,"57588":20723,"57589":20699,"57590":20714,"57591":20701,"57592":20708,"57593":20691,"57594":20716,"57595":20720,"57596":20719,"57597":20707,"57598":20704,"57664":20952,"57665":21120,"57666":21121,"57667":21225,"57668":21227,"57669":21296,"57670":21420,"57671":22055,"57672":22037,"57673":22028,"57674":22034,"57675":22012,"57676":22031,"57677":22044,"57678":22017,"57679":22035,"57680":22018,"57681":22010,"57682":22045,"57683":22020,"57684":22015,"57685":22009,"57686":22665,"57687":22652,"57688":22672,"57689":22680,"57690":22662,"57691":22657,"57692":22655,"57693":22644,"57694":22667,"57695":22650,"57696":22663,"57697":22673,"57698":22670,"57699":22646,"57700":22658,"57701":22664,"57702":22651,"57703":22676,"57704":22671,"57705":22782,"57706":22891,"57707":23260,"57708":23278,"57709":23269,"57710":23253,"57711":23274,"57712":23258,"57713":23277,"57714":23275,"57715":23283,"57716":23266,"57717":23264,"57718":23259,"57719":23276,"57720":23262,"57721":23261,"57722":23257,"57723":23272,"57724":23263,"57725":23415,"57726":23520,"57761":23523,"57762":23651,"57763":23938,"57764":23936,"57765":23933,"57766":23942,"57767":23930,"57768":23937,"57769":23927,"57770":23946,"57771":23945,"57772":23944,"57773":23934,"57774":23932,"57775":23949,"57776":23929,"57777":23935,"57778":24152,"57779":24153,"57780":24147,"57781":24280,"57782":24273,"57783":24279,"57784":24270,"57785":24284,"57786":24277,"57787":24281,"57788":24274,"57789":24276,"57790":24388,"57791":24387,"57792":24431,"57793":24502,"57794":24876,"57795":24872,"57796":24897,"57797":24926,"57798":24945,"57799":24947,"57800":24914,"57801":24915,"57802":24946,"57803":24940,"57804":24960,"57805":24948,"57806":24916,"57807":24954,"57808":24923,"57809":24933,"57810":24891,"57811":24938,"57812":24929,"57813":24918,"57814":25129,"57815":25127,"57816":25131,"57817":25643,"57818":25677,"57819":25691,"57820":25693,"57821":25716,"57822":25718,"57823":25714,"57824":25715,"57825":25725,"57826":25717,"57827":25702,"57828":25766,"57829":25678,"57830":25730,"57831":25694,"57832":25692,"57833":25675,"57834":25683,"57835":25696,"57836":25680,"57837":25727,"57838":25663,"57839":25708,"57840":25707,"57841":25689,"57842":25701,"57843":25719,"57844":25971,"57845":26016,"57846":26273,"57847":26272,"57848":26271,"57849":26373,"57850":26372,"57851":26402,"57852":27057,"57853":27062,"57854":27081,"57920":27040,"57921":27086,"57922":27030,"57923":27056,"57924":27052,"57925":27068,"57926":27025,"57927":27033,"57928":27022,"57929":27047,"57930":27021,"57931":27049,"57932":27070,"57933":27055,"57934":27071,"57935":27076,"57936":27069,"57937":27044,"57938":27092,"57939":27065,"57940":27082,"57941":27034,"57942":27087,"57943":27059,"57944":27027,"57945":27050,"57946":27041,"57947":27038,"57948":27097,"57949":27031,"57950":27024,"57951":27074,"57952":27061,"57953":27045,"57954":27078,"57955":27466,"57956":27469,"57957":27467,"57958":27550,"57959":27551,"57960":27552,"57961":27587,"57962":27588,"57963":27646,"57964":28366,"57965":28405,"57966":28401,"57967":28419,"57968":28453,"57969":28408,"57970":28471,"57971":28411,"57972":28462,"57973":28425,"57974":28494,"57975":28441,"57976":28442,"57977":28455,"57978":28440,"57979":28475,"57980":28434,"57981":28397,"57982":28426,"58017":28470,"58018":28531,"58019":28409,"58020":28398,"58021":28461,"58022":28480,"58023":28464,"58024":28476,"58025":28469,"58026":28395,"58027":28423,"58028":28430,"58029":28483,"58030":28421,"58031":28413,"58032":28406,"58033":28473,"58034":28444,"58035":28412,"58036":28474,"58037":28447,"58038":28429,"58039":28446,"58040":28424,"58041":28449,"58042":29063,"58043":29072,"58044":29065,"58045":29056,"58046":29061,"58047":29058,"58048":29071,"58049":29051,"58050":29062,"58051":29057,"58052":29079,"58053":29252,"58054":29267,"58055":29335,"58056":29333,"58057":29331,"58058":29507,"58059":29517,"58060":29521,"58061":29516,"58062":29794,"58063":29811,"58064":29809,"58065":29813,"58066":29810,"58067":29799,"58068":29806,"58069":29952,"58070":29954,"58071":29955,"58072":30077,"58073":30096,"58074":30230,"58075":30216,"58076":30220,"58077":30229,"58078":30225,"58079":30218,"58080":30228,"58081":30392,"58082":30593,"58083":30588,"58084":30597,"58085":30594,"58086":30574,"58087":30592,"58088":30575,"58089":30590,"58090":30595,"58091":30898,"58092":30890,"58093":30900,"58094":30893,"58095":30888,"58096":30846,"58097":30891,"58098":30878,"58099":30885,"58100":30880,"58101":30892,"58102":30882,"58103":30884,"58104":31128,"58105":31114,"58106":31115,"58107":31126,"58108":31125,"58109":31124,"58110":31123,"58176":31127,"58177":31112,"58178":31122,"58179":31120,"58180":31275,"58181":31306,"58182":31280,"58183":31279,"58184":31272,"58185":31270,"58186":31400,"58187":31403,"58188":31404,"58189":31470,"58190":31624,"58191":31644,"58192":31626,"58193":31633,"58194":31632,"58195":31638,"58196":31629,"58197":31628,"58198":31643,"58199":31630,"58200":31621,"58201":31640,"58202":21124,"58203":31641,"58204":31652,"58205":31618,"58206":31931,"58207":31935,"58208":31932,"58209":31930,"58210":32167,"58211":32183,"58212":32194,"58213":32163,"58214":32170,"58215":32193,"58216":32192,"58217":32197,"58218":32157,"58219":32206,"58220":32196,"58221":32198,"58222":32203,"58223":32204,"58224":32175,"58225":32185,"58226":32150,"58227":32188,"58228":32159,"58229":32166,"58230":32174,"58231":32169,"58232":32161,"58233":32201,"58234":32627,"58235":32738,"58236":32739,"58237":32741,"58238":32734,"58273":32804,"58274":32861,"58275":32860,"58276":33161,"58277":33158,"58278":33155,"58279":33159,"58280":33165,"58281":33164,"58282":33163,"58283":33301,"58284":33943,"58285":33956,"58286":33953,"58287":33951,"58288":33978,"58289":33998,"58290":33986,"58291":33964,"58292":33966,"58293":33963,"58294":33977,"58295":33972,"58296":33985,"58297":33997,"58298":33962,"58299":33946,"58300":33969,"58301":34000,"58302":33949,"58303":33959,"58304":33979,"58305":33954,"58306":33940,"58307":33991,"58308":33996,"58309":33947,"58310":33961,"58311":33967,"58312":33960,"58313":34006,"58314":33944,"58315":33974,"58316":33999,"58317":33952,"58318":34007,"58319":34004,"58320":34002,"58321":34011,"58322":33968,"58323":33937,"58324":34401,"58325":34611,"58326":34595,"58327":34600,"58328":34667,"58329":34624,"58330":34606,"58331":34590,"58332":34593,"58333":34585,"58334":34587,"58335":34627,"58336":34604,"58337":34625,"58338":34622,"58339":34630,"58340":34592,"58341":34610,"58342":34602,"58343":34605,"58344":34620,"58345":34578,"58346":34618,"58347":34609,"58348":34613,"58349":34626,"58350":34598,"58351":34599,"58352":34616,"58353":34596,"58354":34586,"58355":34608,"58356":34577,"58357":35063,"58358":35047,"58359":35057,"58360":35058,"58361":35066,"58362":35070,"58363":35054,"58364":35068,"58365":35062,"58366":35067,"58432":35056,"58433":35052,"58434":35051,"58435":35229,"58436":35233,"58437":35231,"58438":35230,"58439":35305,"58440":35307,"58441":35304,"58442":35499,"58443":35481,"58444":35467,"58445":35474,"58446":35471,"58447":35478,"58448":35901,"58449":35944,"58450":35945,"58451":36053,"58452":36047,"58453":36055,"58454":36246,"58455":36361,"58456":36354,"58457":36351,"58458":36365,"58459":36349,"58460":36362,"58461":36355,"58462":36359,"58463":36358,"58464":36357,"58465":36350,"58466":36352,"58467":36356,"58468":36624,"58469":36625,"58470":36622,"58471":36621,"58472":37155,"58473":37148,"58474":37152,"58475":37154,"58476":37151,"58477":37149,"58478":37146,"58479":37156,"58480":37153,"58481":37147,"58482":37242,"58483":37234,"58484":37241,"58485":37235,"58486":37541,"58487":37540,"58488":37494,"58489":37531,"58490":37498,"58491":37536,"58492":37524,"58493":37546,"58494":37517,"58529":37542,"58530":37530,"58531":37547,"58532":37497,"58533":37527,"58534":37503,"58535":37539,"58536":37614,"58537":37518,"58538":37506,"58539":37525,"58540":37538,"58541":37501,"58542":37512,"58543":37537,"58544":37514,"58545":37510,"58546":37516,"58547":37529,"58548":37543,"58549":37502,"58550":37511,"58551":37545,"58552":37533,"58553":37515,"58554":37421,"58555":38558,"58556":38561,"58557":38655,"58558":38744,"58559":38781,"58560":38778,"58561":38782,"58562":38787,"58563":38784,"58564":38786,"58565":38779,"58566":38788,"58567":38785,"58568":38783,"58569":38862,"58570":38861,"58571":38934,"58572":39085,"58573":39086,"58574":39170,"58575":39168,"58576":39175,"58577":39325,"58578":39324,"58579":39363,"58580":39353,"58581":39355,"58582":39354,"58583":39362,"58584":39357,"58585":39367,"58586":39601,"58587":39651,"58588":39655,"58589":39742,"58590":39743,"58591":39776,"58592":39777,"58593":39775,"58594":40177,"58595":40178,"58596":40181,"58597":40615,"58598":20735,"58599":20739,"58600":20784,"58601":20728,"58602":20742,"58603":20743,"58604":20726,"58605":20734,"58606":20747,"58607":20748,"58608":20733,"58609":20746,"58610":21131,"58611":21132,"58612":21233,"58613":21231,"58614":22088,"58615":22082,"58616":22092,"58617":22069,"58618":22081,"58619":22090,"58620":22089,"58621":22086,"58622":22104,"58688":22106,"58689":22080,"58690":22067,"58691":22077,"58692":22060,"58693":22078,"58694":22072,"58695":22058,"58696":22074,"58697":22298,"58698":22699,"58699":22685,"58700":22705,"58701":22688,"58702":22691,"58703":22703,"58704":22700,"58705":22693,"58706":22689,"58707":22783,"58708":23295,"58709":23284,"58710":23293,"58711":23287,"58712":23286,"58713":23299,"58714":23288,"58715":23298,"58716":23289,"58717":23297,"58718":23303,"58719":23301,"58720":23311,"58721":23655,"58722":23961,"58723":23959,"58724":23967,"58725":23954,"58726":23970,"58727":23955,"58728":23957,"58729":23968,"58730":23964,"58731":23969,"58732":23962,"58733":23966,"58734":24169,"58735":24157,"58736":24160,"58737":24156,"58738":32243,"58739":24283,"58740":24286,"58741":24289,"58742":24393,"58743":24498,"58744":24971,"58745":24963,"58746":24953,"58747":25009,"58748":25008,"58749":24994,"58750":24969,"58785":24987,"58786":24979,"58787":25007,"58788":25005,"58789":24991,"58790":24978,"58791":25002,"58792":24993,"58793":24973,"58794":24934,"58795":25011,"58796":25133,"58797":25710,"58798":25712,"58799":25750,"58800":25760,"58801":25733,"58802":25751,"58803":25756,"58804":25743,"58805":25739,"58806":25738,"58807":25740,"58808":25763,"58809":25759,"58810":25704,"58811":25777,"58812":25752,"58813":25974,"58814":25978,"58815":25977,"58816":25979,"58817":26034,"58818":26035,"58819":26293,"58820":26288,"58821":26281,"58822":26290,"58823":26295,"58824":26282,"58825":26287,"58826":27136,"58827":27142,"58828":27159,"58829":27109,"58830":27128,"58831":27157,"58832":27121,"58833":27108,"58834":27168,"58835":27135,"58836":27116,"58837":27106,"58838":27163,"58839":27165,"58840":27134,"58841":27175,"58842":27122,"58843":27118,"58844":27156,"58845":27127,"58846":27111,"58847":27200,"58848":27144,"58849":27110,"58850":27131,"58851":27149,"58852":27132,"58853":27115,"58854":27145,"58855":27140,"58856":27160,"58857":27173,"58858":27151,"58859":27126,"58860":27174,"58861":27143,"58862":27124,"58863":27158,"58864":27473,"58865":27557,"58866":27555,"58867":27554,"58868":27558,"58869":27649,"58870":27648,"58871":27647,"58872":27650,"58873":28481,"58874":28454,"58875":28542,"58876":28551,"58877":28614,"58878":28562,"58944":28557,"58945":28553,"58946":28556,"58947":28514,"58948":28495,"58949":28549,"58950":28506,"58951":28566,"58952":28534,"58953":28524,"58954":28546,"58955":28501,"58956":28530,"58957":28498,"58958":28496,"58959":28503,"58960":28564,"58961":28563,"58962":28509,"58963":28416,"58964":28513,"58965":28523,"58966":28541,"58967":28519,"58968":28560,"58969":28499,"58970":28555,"58971":28521,"58972":28543,"58973":28565,"58974":28515,"58975":28535,"58976":28522,"58977":28539,"58978":29106,"58979":29103,"58980":29083,"58981":29104,"58982":29088,"58983":29082,"58984":29097,"58985":29109,"58986":29085,"58987":29093,"58988":29086,"58989":29092,"58990":29089,"58991":29098,"58992":29084,"58993":29095,"58994":29107,"58995":29336,"58996":29338,"58997":29528,"58998":29522,"58999":29534,"59000":29535,"59001":29536,"59002":29533,"59003":29531,"59004":29537,"59005":29530,"59006":29529,"59041":29538,"59042":29831,"59043":29833,"59044":29834,"59045":29830,"59046":29825,"59047":29821,"59048":29829,"59049":29832,"59050":29820,"59051":29817,"59052":29960,"59053":29959,"59054":30078,"59055":30245,"59056":30238,"59057":30233,"59058":30237,"59059":30236,"59060":30243,"59061":30234,"59062":30248,"59063":30235,"59064":30364,"59065":30365,"59066":30366,"59067":30363,"59068":30605,"59069":30607,"59070":30601,"59071":30600,"59072":30925,"59073":30907,"59074":30927,"59075":30924,"59076":30929,"59077":30926,"59078":30932,"59079":30920,"59080":30915,"59081":30916,"59082":30921,"59083":31130,"59084":31137,"59085":31136,"59086":31132,"59087":31138,"59088":31131,"59089":27510,"59090":31289,"59091":31410,"59092":31412,"59093":31411,"59094":31671,"59095":31691,"59096":31678,"59097":31660,"59098":31694,"59099":31663,"59100":31673,"59101":31690,"59102":31669,"59103":31941,"59104":31944,"59105":31948,"59106":31947,"59107":32247,"59108":32219,"59109":32234,"59110":32231,"59111":32215,"59112":32225,"59113":32259,"59114":32250,"59115":32230,"59116":32246,"59117":32241,"59118":32240,"59119":32238,"59120":32223,"59121":32630,"59122":32684,"59123":32688,"59124":32685,"59125":32749,"59126":32747,"59127":32746,"59128":32748,"59129":32742,"59130":32744,"59131":32868,"59132":32871,"59133":33187,"59134":33183,"59200":33182,"59201":33173,"59202":33186,"59203":33177,"59204":33175,"59205":33302,"59206":33359,"59207":33363,"59208":33362,"59209":33360,"59210":33358,"59211":33361,"59212":34084,"59213":34107,"59214":34063,"59215":34048,"59216":34089,"59217":34062,"59218":34057,"59219":34061,"59220":34079,"59221":34058,"59222":34087,"59223":34076,"59224":34043,"59225":34091,"59226":34042,"59227":34056,"59228":34060,"59229":34036,"59230":34090,"59231":34034,"59232":34069,"59233":34039,"59234":34027,"59235":34035,"59236":34044,"59237":34066,"59238":34026,"59239":34025,"59240":34070,"59241":34046,"59242":34088,"59243":34077,"59244":34094,"59245":34050,"59246":34045,"59247":34078,"59248":34038,"59249":34097,"59250":34086,"59251":34023,"59252":34024,"59253":34032,"59254":34031,"59255":34041,"59256":34072,"59257":34080,"59258":34096,"59259":34059,"59260":34073,"59261":34095,"59262":34402,"59297":34646,"59298":34659,"59299":34660,"59300":34679,"59301":34785,"59302":34675,"59303":34648,"59304":34644,"59305":34651,"59306":34642,"59307":34657,"59308":34650,"59309":34641,"59310":34654,"59311":34669,"59312":34666,"59313":34640,"59314":34638,"59315":34655,"59316":34653,"59317":34671,"59318":34668,"59319":34682,"59320":34670,"59321":34652,"59322":34661,"59323":34639,"59324":34683,"59325":34677,"59326":34658,"59327":34663,"59328":34665,"59329":34906,"59330":35077,"59331":35084,"59332":35092,"59333":35083,"59334":35095,"59335":35096,"59336":35097,"59337":35078,"59338":35094,"59339":35089,"59340":35086,"59341":35081,"59342":35234,"59343":35236,"59344":35235,"59345":35309,"59346":35312,"59347":35308,"59348":35535,"59349":35526,"59350":35512,"59351":35539,"59352":35537,"59353":35540,"59354":35541,"59355":35515,"59356":35543,"59357":35518,"59358":35520,"59359":35525,"59360":35544,"59361":35523,"59362":35514,"59363":35517,"59364":35545,"59365":35902,"59366":35917,"59367":35983,"59368":36069,"59369":36063,"59370":36057,"59371":36072,"59372":36058,"59373":36061,"59374":36071,"59375":36256,"59376":36252,"59377":36257,"59378":36251,"59379":36384,"59380":36387,"59381":36389,"59382":36388,"59383":36398,"59384":36373,"59385":36379,"59386":36374,"59387":36369,"59388":36377,"59389":36390,"59390":36391,"59456":36372,"59457":36370,"59458":36376,"59459":36371,"59460":36380,"59461":36375,"59462":36378,"59463":36652,"59464":36644,"59465":36632,"59466":36634,"59467":36640,"59468":36643,"59469":36630,"59470":36631,"59471":36979,"59472":36976,"59473":36975,"59474":36967,"59475":36971,"59476":37167,"59477":37163,"59478":37161,"59479":37162,"59480":37170,"59481":37158,"59482":37166,"59483":37253,"59484":37254,"59485":37258,"59486":37249,"59487":37250,"59488":37252,"59489":37248,"59490":37584,"59491":37571,"59492":37572,"59493":37568,"59494":37593,"59495":37558,"59496":37583,"59497":37617,"59498":37599,"59499":37592,"59500":37609,"59501":37591,"59502":37597,"59503":37580,"59504":37615,"59505":37570,"59506":37608,"59507":37578,"59508":37576,"59509":37582,"59510":37606,"59511":37581,"59512":37589,"59513":37577,"59514":37600,"59515":37598,"59516":37607,"59517":37585,"59518":37587,"59553":37557,"59554":37601,"59555":37574,"59556":37556,"59557":38268,"59558":38316,"59559":38315,"59560":38318,"59561":38320,"59562":38564,"59563":38562,"59564":38611,"59565":38661,"59566":38664,"59567":38658,"59568":38746,"59569":38794,"59570":38798,"59571":38792,"59572":38864,"59573":38863,"59574":38942,"59575":38941,"59576":38950,"59577":38953,"59578":38952,"59579":38944,"59580":38939,"59581":38951,"59582":39090,"59583":39176,"59584":39162,"59585":39185,"59586":39188,"59587":39190,"59588":39191,"59589":39189,"59590":39388,"59591":39373,"59592":39375,"59593":39379,"59594":39380,"59595":39374,"59596":39369,"59597":39382,"59598":39384,"59599":39371,"59600":39383,"59601":39372,"59602":39603,"59603":39660,"59604":39659,"59605":39667,"59606":39666,"59607":39665,"59608":39750,"59609":39747,"59610":39783,"59611":39796,"59612":39793,"59613":39782,"59614":39798,"59615":39797,"59616":39792,"59617":39784,"59618":39780,"59619":39788,"59620":40188,"59621":40186,"59622":40189,"59623":40191,"59624":40183,"59625":40199,"59626":40192,"59627":40185,"59628":40187,"59629":40200,"59630":40197,"59631":40196,"59632":40579,"59633":40659,"59634":40719,"59635":40720,"59636":20764,"59637":20755,"59638":20759,"59639":20762,"59640":20753,"59641":20958,"59642":21300,"59643":21473,"59644":22128,"59645":22112,"59646":22126,"59712":22131,"59713":22118,"59714":22115,"59715":22125,"59716":22130,"59717":22110,"59718":22135,"59719":22300,"59720":22299,"59721":22728,"59722":22717,"59723":22729,"59724":22719,"59725":22714,"59726":22722,"59727":22716,"59728":22726,"59729":23319,"59730":23321,"59731":23323,"59732":23329,"59733":23316,"59734":23315,"59735":23312,"59736":23318,"59737":23336,"59738":23322,"59739":23328,"59740":23326,"59741":23535,"59742":23980,"59743":23985,"59744":23977,"59745":23975,"59746":23989,"59747":23984,"59748":23982,"59749":23978,"59750":23976,"59751":23986,"59752":23981,"59753":23983,"59754":23988,"59755":24167,"59756":24168,"59757":24166,"59758":24175,"59759":24297,"59760":24295,"59761":24294,"59762":24296,"59763":24293,"59764":24395,"59765":24508,"59766":24989,"59767":25000,"59768":24982,"59769":25029,"59770":25012,"59771":25030,"59772":25025,"59773":25036,"59774":25018,"59809":25023,"59810":25016,"59811":24972,"59812":25815,"59813":25814,"59814":25808,"59815":25807,"59816":25801,"59817":25789,"59818":25737,"59819":25795,"59820":25819,"59821":25843,"59822":25817,"59823":25907,"59824":25983,"59825":25980,"59826":26018,"59827":26312,"59828":26302,"59829":26304,"59830":26314,"59831":26315,"59832":26319,"59833":26301,"59834":26299,"59835":26298,"59836":26316,"59837":26403,"59838":27188,"59839":27238,"59840":27209,"59841":27239,"59842":27186,"59843":27240,"59844":27198,"59845":27229,"59846":27245,"59847":27254,"59848":27227,"59849":27217,"59850":27176,"59851":27226,"59852":27195,"59853":27199,"59854":27201,"59855":27242,"59856":27236,"59857":27216,"59858":27215,"59859":27220,"59860":27247,"59861":27241,"59862":27232,"59863":27196,"59864":27230,"59865":27222,"59866":27221,"59867":27213,"59868":27214,"59869":27206,"59870":27477,"59871":27476,"59872":27478,"59873":27559,"59874":27562,"59875":27563,"59876":27592,"59877":27591,"59878":27652,"59879":27651,"59880":27654,"59881":28589,"59882":28619,"59883":28579,"59884":28615,"59885":28604,"59886":28622,"59887":28616,"59888":28510,"59889":28612,"59890":28605,"59891":28574,"59892":28618,"59893":28584,"59894":28676,"59895":28581,"59896":28590,"59897":28602,"59898":28588,"59899":28586,"59900":28623,"59901":28607,"59902":28600,"59968":28578,"59969":28617,"59970":28587,"59971":28621,"59972":28591,"59973":28594,"59974":28592,"59975":29125,"59976":29122,"59977":29119,"59978":29112,"59979":29142,"59980":29120,"59981":29121,"59982":29131,"59983":29140,"59984":29130,"59985":29127,"59986":29135,"59987":29117,"59988":29144,"59989":29116,"59990":29126,"59991":29146,"59992":29147,"59993":29341,"59994":29342,"59995":29545,"59996":29542,"59997":29543,"59998":29548,"59999":29541,"60000":29547,"60001":29546,"60002":29823,"60003":29850,"60004":29856,"60005":29844,"60006":29842,"60007":29845,"60008":29857,"60009":29963,"60010":30080,"60011":30255,"60012":30253,"60013":30257,"60014":30269,"60015":30259,"60016":30268,"60017":30261,"60018":30258,"60019":30256,"60020":30395,"60021":30438,"60022":30618,"60023":30621,"60024":30625,"60025":30620,"60026":30619,"60027":30626,"60028":30627,"60029":30613,"60030":30617,"60065":30615,"60066":30941,"60067":30953,"60068":30949,"60069":30954,"60070":30942,"60071":30947,"60072":30939,"60073":30945,"60074":30946,"60075":30957,"60076":30943,"60077":30944,"60078":31140,"60079":31300,"60080":31304,"60081":31303,"60082":31414,"60083":31416,"60084":31413,"60085":31409,"60086":31415,"60087":31710,"60088":31715,"60089":31719,"60090":31709,"60091":31701,"60092":31717,"60093":31706,"60094":31720,"60095":31737,"60096":31700,"60097":31722,"60098":31714,"60099":31708,"60100":31723,"60101":31704,"60102":31711,"60103":31954,"60104":31956,"60105":31959,"60106":31952,"60107":31953,"60108":32274,"60109":32289,"60110":32279,"60111":32268,"60112":32287,"60113":32288,"60114":32275,"60115":32270,"60116":32284,"60117":32277,"60118":32282,"60119":32290,"60120":32267,"60121":32271,"60122":32278,"60123":32269,"60124":32276,"60125":32293,"60126":32292,"60127":32579,"60128":32635,"60129":32636,"60130":32634,"60131":32689,"60132":32751,"60133":32810,"60134":32809,"60135":32876,"60136":33201,"60137":33190,"60138":33198,"60139":33209,"60140":33205,"60141":33195,"60142":33200,"60143":33196,"60144":33204,"60145":33202,"60146":33207,"60147":33191,"60148":33266,"60149":33365,"60150":33366,"60151":33367,"60152":34134,"60153":34117,"60154":34155,"60155":34125,"60156":34131,"60157":34145,"60158":34136,"60224":34112,"60225":34118,"60226":34148,"60227":34113,"60228":34146,"60229":34116,"60230":34129,"60231":34119,"60232":34147,"60233":34110,"60234":34139,"60235":34161,"60236":34126,"60237":34158,"60238":34165,"60239":34133,"60240":34151,"60241":34144,"60242":34188,"60243":34150,"60244":34141,"60245":34132,"60246":34149,"60247":34156,"60248":34403,"60249":34405,"60250":34404,"60251":34715,"60252":34703,"60253":34711,"60254":34707,"60255":34706,"60256":34696,"60257":34689,"60258":34710,"60259":34712,"60260":34681,"60261":34695,"60262":34723,"60263":34693,"60264":34704,"60265":34705,"60266":34717,"60267":34692,"60268":34708,"60269":34716,"60270":34714,"60271":34697,"60272":35102,"60273":35110,"60274":35120,"60275":35117,"60276":35118,"60277":35111,"60278":35121,"60279":35106,"60280":35113,"60281":35107,"60282":35119,"60283":35116,"60284":35103,"60285":35313,"60286":35552,"60321":35554,"60322":35570,"60323":35572,"60324":35573,"60325":35549,"60326":35604,"60327":35556,"60328":35551,"60329":35568,"60330":35528,"60331":35550,"60332":35553,"60333":35560,"60334":35583,"60335":35567,"60336":35579,"60337":35985,"60338":35986,"60339":35984,"60340":36085,"60341":36078,"60342":36081,"60343":36080,"60344":36083,"60345":36204,"60346":36206,"60347":36261,"60348":36263,"60349":36403,"60350":36414,"60351":36408,"60352":36416,"60353":36421,"60354":36406,"60355":36412,"60356":36413,"60357":36417,"60358":36400,"60359":36415,"60360":36541,"60361":36662,"60362":36654,"60363":36661,"60364":36658,"60365":36665,"60366":36663,"60367":36660,"60368":36982,"60369":36985,"60370":36987,"60371":36998,"60372":37114,"60373":37171,"60374":37173,"60375":37174,"60376":37267,"60377":37264,"60378":37265,"60379":37261,"60380":37263,"60381":37671,"60382":37662,"60383":37640,"60384":37663,"60385":37638,"60386":37647,"60387":37754,"60388":37688,"60389":37692,"60390":37659,"60391":37667,"60392":37650,"60393":37633,"60394":37702,"60395":37677,"60396":37646,"60397":37645,"60398":37579,"60399":37661,"60400":37626,"60401":37669,"60402":37651,"60403":37625,"60404":37623,"60405":37684,"60406":37634,"60407":37668,"60408":37631,"60409":37673,"60410":37689,"60411":37685,"60412":37674,"60413":37652,"60414":37644,"60480":37643,"60481":37630,"60482":37641,"60483":37632,"60484":37627,"60485":37654,"60486":38332,"60487":38349,"60488":38334,"60489":38329,"60490":38330,"60491":38326,"60492":38335,"60493":38325,"60494":38333,"60495":38569,"60496":38612,"60497":38667,"60498":38674,"60499":38672,"60500":38809,"60501":38807,"60502":38804,"60503":38896,"60504":38904,"60505":38965,"60506":38959,"60507":38962,"60508":39204,"60509":39199,"60510":39207,"60511":39209,"60512":39326,"60513":39406,"60514":39404,"60515":39397,"60516":39396,"60517":39408,"60518":39395,"60519":39402,"60520":39401,"60521":39399,"60522":39609,"60523":39615,"60524":39604,"60525":39611,"60526":39670,"60527":39674,"60528":39673,"60529":39671,"60530":39731,"60531":39808,"60532":39813,"60533":39815,"60534":39804,"60535":39806,"60536":39803,"60537":39810,"60538":39827,"60539":39826,"60540":39824,"60541":39802,"60542":39829,"60577":39805,"60578":39816,"60579":40229,"60580":40215,"60581":40224,"60582":40222,"60583":40212,"60584":40233,"60585":40221,"60586":40216,"60587":40226,"60588":40208,"60589":40217,"60590":40223,"60591":40584,"60592":40582,"60593":40583,"60594":40622,"60595":40621,"60596":40661,"60597":40662,"60598":40698,"60599":40722,"60600":40765,"60601":20774,"60602":20773,"60603":20770,"60604":20772,"60605":20768,"60606":20777,"60607":21236,"60608":22163,"60609":22156,"60610":22157,"60611":22150,"60612":22148,"60613":22147,"60614":22142,"60615":22146,"60616":22143,"60617":22145,"60618":22742,"60619":22740,"60620":22735,"60621":22738,"60622":23341,"60623":23333,"60624":23346,"60625":23331,"60626":23340,"60627":23335,"60628":23334,"60629":23343,"60630":23342,"60631":23419,"60632":23537,"60633":23538,"60634":23991,"60635":24172,"60636":24170,"60637":24510,"60638":24507,"60639":25027,"60640":25013,"60641":25020,"60642":25063,"60643":25056,"60644":25061,"60645":25060,"60646":25064,"60647":25054,"60648":25839,"60649":25833,"60650":25827,"60651":25835,"60652":25828,"60653":25832,"60654":25985,"60655":25984,"60656":26038,"60657":26074,"60658":26322,"60659":27277,"60660":27286,"60661":27265,"60662":27301,"60663":27273,"60664":27295,"60665":27291,"60666":27297,"60667":27294,"60668":27271,"60669":27283,"60670":27278,"60736":27285,"60737":27267,"60738":27304,"60739":27300,"60740":27281,"60741":27263,"60742":27302,"60743":27290,"60744":27269,"60745":27276,"60746":27282,"60747":27483,"60748":27565,"60749":27657,"60750":28620,"60751":28585,"60752":28660,"60753":28628,"60754":28643,"60755":28636,"60756":28653,"60757":28647,"60758":28646,"60759":28638,"60760":28658,"60761":28637,"60762":28642,"60763":28648,"60764":29153,"60765":29169,"60766":29160,"60767":29170,"60768":29156,"60769":29168,"60770":29154,"60771":29555,"60772":29550,"60773":29551,"60774":29847,"60775":29874,"60776":29867,"60777":29840,"60778":29866,"60779":29869,"60780":29873,"60781":29861,"60782":29871,"60783":29968,"60784":29969,"60785":29970,"60786":29967,"60787":30084,"60788":30275,"60789":30280,"60790":30281,"60791":30279,"60792":30372,"60793":30441,"60794":30645,"60795":30635,"60796":30642,"60797":30647,"60798":30646,"60833":30644,"60834":30641,"60835":30632,"60836":30704,"60837":30963,"60838":30973,"60839":30978,"60840":30971,"60841":30972,"60842":30962,"60843":30981,"60844":30969,"60845":30974,"60846":30980,"60847":31147,"60848":31144,"60849":31324,"60850":31323,"60851":31318,"60852":31320,"60853":31316,"60854":31322,"60855":31422,"60856":31424,"60857":31425,"60858":31749,"60859":31759,"60860":31730,"60861":31744,"60862":31743,"60863":31739,"60864":31758,"60865":31732,"60866":31755,"60867":31731,"60868":31746,"60869":31753,"60870":31747,"60871":31745,"60872":31736,"60873":31741,"60874":31750,"60875":31728,"60876":31729,"60877":31760,"60878":31754,"60879":31976,"60880":32301,"60881":32316,"60882":32322,"60883":32307,"60884":38984,"60885":32312,"60886":32298,"60887":32329,"60888":32320,"60889":32327,"60890":32297,"60891":32332,"60892":32304,"60893":32315,"60894":32310,"60895":32324,"60896":32314,"60897":32581,"60898":32639,"60899":32638,"60900":32637,"60901":32756,"60902":32754,"60903":32812,"60904":33211,"60905":33220,"60906":33228,"60907":33226,"60908":33221,"60909":33223,"60910":33212,"60911":33257,"60912":33371,"60913":33370,"60914":33372,"60915":34179,"60916":34176,"60917":34191,"60918":34215,"60919":34197,"60920":34208,"60921":34187,"60922":34211,"60923":34171,"60924":34212,"60925":34202,"60926":34206,"60992":34167,"60993":34172,"60994":34185,"60995":34209,"60996":34170,"60997":34168,"60998":34135,"60999":34190,"61000":34198,"61001":34182,"61002":34189,"61003":34201,"61004":34205,"61005":34177,"61006":34210,"61007":34178,"61008":34184,"61009":34181,"61010":34169,"61011":34166,"61012":34200,"61013":34192,"61014":34207,"61015":34408,"61016":34750,"61017":34730,"61018":34733,"61019":34757,"61020":34736,"61021":34732,"61022":34745,"61023":34741,"61024":34748,"61025":34734,"61026":34761,"61027":34755,"61028":34754,"61029":34764,"61030":34743,"61031":34735,"61032":34756,"61033":34762,"61034":34740,"61035":34742,"61036":34751,"61037":34744,"61038":34749,"61039":34782,"61040":34738,"61041":35125,"61042":35123,"61043":35132,"61044":35134,"61045":35137,"61046":35154,"61047":35127,"61048":35138,"61049":35245,"61050":35247,"61051":35246,"61052":35314,"61053":35315,"61054":35614,"61089":35608,"61090":35606,"61091":35601,"61092":35589,"61093":35595,"61094":35618,"61095":35599,"61096":35602,"61097":35605,"61098":35591,"61099":35597,"61100":35592,"61101":35590,"61102":35612,"61103":35603,"61104":35610,"61105":35919,"61106":35952,"61107":35954,"61108":35953,"61109":35951,"61110":35989,"61111":35988,"61112":36089,"61113":36207,"61114":36430,"61115":36429,"61116":36435,"61117":36432,"61118":36428,"61119":36423,"61120":36675,"61121":36672,"61122":36997,"61123":36990,"61124":37176,"61125":37274,"61126":37282,"61127":37275,"61128":37273,"61129":37279,"61130":37281,"61131":37277,"61132":37280,"61133":37793,"61134":37763,"61135":37807,"61136":37732,"61137":37718,"61138":37703,"61139":37756,"61140":37720,"61141":37724,"61142":37750,"61143":37705,"61144":37712,"61145":37713,"61146":37728,"61147":37741,"61148":37775,"61149":37708,"61150":37738,"61151":37753,"61152":37719,"61153":37717,"61154":37714,"61155":37711,"61156":37745,"61157":37751,"61158":37755,"61159":37729,"61160":37726,"61161":37731,"61162":37735,"61163":37760,"61164":37710,"61165":37721,"61166":38343,"61167":38336,"61168":38345,"61169":38339,"61170":38341,"61171":38327,"61172":38574,"61173":38576,"61174":38572,"61175":38688,"61176":38687,"61177":38680,"61178":38685,"61179":38681,"61180":38810,"61181":38817,"61182":38812,"61248":38814,"61249":38813,"61250":38869,"61251":38868,"61252":38897,"61253":38977,"61254":38980,"61255":38986,"61256":38985,"61257":38981,"61258":38979,"61259":39205,"61260":39211,"61261":39212,"61262":39210,"61263":39219,"61264":39218,"61265":39215,"61266":39213,"61267":39217,"61268":39216,"61269":39320,"61270":39331,"61271":39329,"61272":39426,"61273":39418,"61274":39412,"61275":39415,"61276":39417,"61277":39416,"61278":39414,"61279":39419,"61280":39421,"61281":39422,"61282":39420,"61283":39427,"61284":39614,"61285":39678,"61286":39677,"61287":39681,"61288":39676,"61289":39752,"61290":39834,"61291":39848,"61292":39838,"61293":39835,"61294":39846,"61295":39841,"61296":39845,"61297":39844,"61298":39814,"61299":39842,"61300":39840,"61301":39855,"61302":40243,"61303":40257,"61304":40295,"61305":40246,"61306":40238,"61307":40239,"61308":40241,"61309":40248,"61310":40240,"61345":40261,"61346":40258,"61347":40259,"61348":40254,"61349":40247,"61350":40256,"61351":40253,"61352":32757,"61353":40237,"61354":40586,"61355":40585,"61356":40589,"61357":40624,"61358":40648,"61359":40666,"61360":40699,"61361":40703,"61362":40740,"61363":40739,"61364":40738,"61365":40788,"61366":40864,"61367":20785,"61368":20781,"61369":20782,"61370":22168,"61371":22172,"61372":22167,"61373":22170,"61374":22173,"61375":22169,"61376":22896,"61377":23356,"61378":23657,"61379":23658,"61380":24000,"61381":24173,"61382":24174,"61383":25048,"61384":25055,"61385":25069,"61386":25070,"61387":25073,"61388":25066,"61389":25072,"61390":25067,"61391":25046,"61392":25065,"61393":25855,"61394":25860,"61395":25853,"61396":25848,"61397":25857,"61398":25859,"61399":25852,"61400":26004,"61401":26075,"61402":26330,"61403":26331,"61404":26328,"61405":27333,"61406":27321,"61407":27325,"61408":27361,"61409":27334,"61410":27322,"61411":27318,"61412":27319,"61413":27335,"61414":27316,"61415":27309,"61416":27486,"61417":27593,"61418":27659,"61419":28679,"61420":28684,"61421":28685,"61422":28673,"61423":28677,"61424":28692,"61425":28686,"61426":28671,"61427":28672,"61428":28667,"61429":28710,"61430":28668,"61431":28663,"61432":28682,"61433":29185,"61434":29183,"61435":29177,"61436":29187,"61437":29181,"61438":29558,"61504":29880,"61505":29888,"61506":29877,"61507":29889,"61508":29886,"61509":29878,"61510":29883,"61511":29890,"61512":29972,"61513":29971,"61514":30300,"61515":30308,"61516":30297,"61517":30288,"61518":30291,"61519":30295,"61520":30298,"61521":30374,"61522":30397,"61523":30444,"61524":30658,"61525":30650,"61526":30975,"61527":30988,"61528":30995,"61529":30996,"61530":30985,"61531":30992,"61532":30994,"61533":30993,"61534":31149,"61535":31148,"61536":31327,"61537":31772,"61538":31785,"61539":31769,"61540":31776,"61541":31775,"61542":31789,"61543":31773,"61544":31782,"61545":31784,"61546":31778,"61547":31781,"61548":31792,"61549":32348,"61550":32336,"61551":32342,"61552":32355,"61553":32344,"61554":32354,"61555":32351,"61556":32337,"61557":32352,"61558":32343,"61559":32339,"61560":32693,"61561":32691,"61562":32759,"61563":32760,"61564":32885,"61565":33233,"61566":33234,"61601":33232,"61602":33375,"61603":33374,"61604":34228,"61605":34246,"61606":34240,"61607":34243,"61608":34242,"61609":34227,"61610":34229,"61611":34237,"61612":34247,"61613":34244,"61614":34239,"61615":34251,"61616":34254,"61617":34248,"61618":34245,"61619":34225,"61620":34230,"61621":34258,"61622":34340,"61623":34232,"61624":34231,"61625":34238,"61626":34409,"61627":34791,"61628":34790,"61629":34786,"61630":34779,"61631":34795,"61632":34794,"61633":34789,"61634":34783,"61635":34803,"61636":34788,"61637":34772,"61638":34780,"61639":34771,"61640":34797,"61641":34776,"61642":34787,"61643":34724,"61644":34775,"61645":34777,"61646":34817,"61647":34804,"61648":34792,"61649":34781,"61650":35155,"61651":35147,"61652":35151,"61653":35148,"61654":35142,"61655":35152,"61656":35153,"61657":35145,"61658":35626,"61659":35623,"61660":35619,"61661":35635,"61662":35632,"61663":35637,"61664":35655,"61665":35631,"61666":35644,"61667":35646,"61668":35633,"61669":35621,"61670":35639,"61671":35622,"61672":35638,"61673":35630,"61674":35620,"61675":35643,"61676":35645,"61677":35642,"61678":35906,"61679":35957,"61680":35993,"61681":35992,"61682":35991,"61683":36094,"61684":36100,"61685":36098,"61686":36096,"61687":36444,"61688":36450,"61689":36448,"61690":36439,"61691":36438,"61692":36446,"61693":36453,"61694":36455,"61760":36443,"61761":36442,"61762":36449,"61763":36445,"61764":36457,"61765":36436,"61766":36678,"61767":36679,"61768":36680,"61769":36683,"61770":37160,"61771":37178,"61772":37179,"61773":37182,"61774":37288,"61775":37285,"61776":37287,"61777":37295,"61778":37290,"61779":37813,"61780":37772,"61781":37778,"61782":37815,"61783":37787,"61784":37789,"61785":37769,"61786":37799,"61787":37774,"61788":37802,"61789":37790,"61790":37798,"61791":37781,"61792":37768,"61793":37785,"61794":37791,"61795":37773,"61796":37809,"61797":37777,"61798":37810,"61799":37796,"61800":37800,"61801":37812,"61802":37795,"61803":37797,"61804":38354,"61805":38355,"61806":38353,"61807":38579,"61808":38615,"61809":38618,"61810":24002,"61811":38623,"61812":38616,"61813":38621,"61814":38691,"61815":38690,"61816":38693,"61817":38828,"61818":38830,"61819":38824,"61820":38827,"61821":38820,"61822":38826,"61857":38818,"61858":38821,"61859":38871,"61860":38873,"61861":38870,"61862":38872,"61863":38906,"61864":38992,"61865":38993,"61866":38994,"61867":39096,"61868":39233,"61869":39228,"61870":39226,"61871":39439,"61872":39435,"61873":39433,"61874":39437,"61875":39428,"61876":39441,"61877":39434,"61878":39429,"61879":39431,"61880":39430,"61881":39616,"61882":39644,"61883":39688,"61884":39684,"61885":39685,"61886":39721,"61887":39733,"61888":39754,"61889":39756,"61890":39755,"61891":39879,"61892":39878,"61893":39875,"61894":39871,"61895":39873,"61896":39861,"61897":39864,"61898":39891,"61899":39862,"61900":39876,"61901":39865,"61902":39869,"61903":40284,"61904":40275,"61905":40271,"61906":40266,"61907":40283,"61908":40267,"61909":40281,"61910":40278,"61911":40268,"61912":40279,"61913":40274,"61914":40276,"61915":40287,"61916":40280,"61917":40282,"61918":40590,"61919":40588,"61920":40671,"61921":40705,"61922":40704,"61923":40726,"61924":40741,"61925":40747,"61926":40746,"61927":40745,"61928":40744,"61929":40780,"61930":40789,"61931":20788,"61932":20789,"61933":21142,"61934":21239,"61935":21428,"61936":22187,"61937":22189,"61938":22182,"61939":22183,"61940":22186,"61941":22188,"61942":22746,"61943":22749,"61944":22747,"61945":22802,"61946":23357,"61947":23358,"61948":23359,"61949":24003,"61950":24176,"62016":24511,"62017":25083,"62018":25863,"62019":25872,"62020":25869,"62021":25865,"62022":25868,"62023":25870,"62024":25988,"62025":26078,"62026":26077,"62027":26334,"62028":27367,"62029":27360,"62030":27340,"62031":27345,"62032":27353,"62033":27339,"62034":27359,"62035":27356,"62036":27344,"62037":27371,"62038":27343,"62039":27341,"62040":27358,"62041":27488,"62042":27568,"62043":27660,"62044":28697,"62045":28711,"62046":28704,"62047":28694,"62048":28715,"62049":28705,"62050":28706,"62051":28707,"62052":28713,"62053":28695,"62054":28708,"62055":28700,"62056":28714,"62057":29196,"62058":29194,"62059":29191,"62060":29186,"62061":29189,"62062":29349,"62063":29350,"62064":29348,"62065":29347,"62066":29345,"62067":29899,"62068":29893,"62069":29879,"62070":29891,"62071":29974,"62072":30304,"62073":30665,"62074":30666,"62075":30660,"62076":30705,"62077":31005,"62078":31003,"62113":31009,"62114":31004,"62115":30999,"62116":31006,"62117":31152,"62118":31335,"62119":31336,"62120":31795,"62121":31804,"62122":31801,"62123":31788,"62124":31803,"62125":31980,"62126":31978,"62127":32374,"62128":32373,"62129":32376,"62130":32368,"62131":32375,"62132":32367,"62133":32378,"62134":32370,"62135":32372,"62136":32360,"62137":32587,"62138":32586,"62139":32643,"62140":32646,"62141":32695,"62142":32765,"62143":32766,"62144":32888,"62145":33239,"62146":33237,"62147":33380,"62148":33377,"62149":33379,"62150":34283,"62151":34289,"62152":34285,"62153":34265,"62154":34273,"62155":34280,"62156":34266,"62157":34263,"62158":34284,"62159":34290,"62160":34296,"62161":34264,"62162":34271,"62163":34275,"62164":34268,"62165":34257,"62166":34288,"62167":34278,"62168":34287,"62169":34270,"62170":34274,"62171":34816,"62172":34810,"62173":34819,"62174":34806,"62175":34807,"62176":34825,"62177":34828,"62178":34827,"62179":34822,"62180":34812,"62181":34824,"62182":34815,"62183":34826,"62184":34818,"62185":35170,"62186":35162,"62187":35163,"62188":35159,"62189":35169,"62190":35164,"62191":35160,"62192":35165,"62193":35161,"62194":35208,"62195":35255,"62196":35254,"62197":35318,"62198":35664,"62199":35656,"62200":35658,"62201":35648,"62202":35667,"62203":35670,"62204":35668,"62205":35659,"62206":35669,"62272":35665,"62273":35650,"62274":35666,"62275":35671,"62276":35907,"62277":35959,"62278":35958,"62279":35994,"62280":36102,"62281":36103,"62282":36105,"62283":36268,"62284":36266,"62285":36269,"62286":36267,"62287":36461,"62288":36472,"62289":36467,"62290":36458,"62291":36463,"62292":36475,"62293":36546,"62294":36690,"62295":36689,"62296":36687,"62297":36688,"62298":36691,"62299":36788,"62300":37184,"62301":37183,"62302":37296,"62303":37293,"62304":37854,"62305":37831,"62306":37839,"62307":37826,"62308":37850,"62309":37840,"62310":37881,"62311":37868,"62312":37836,"62313":37849,"62314":37801,"62315":37862,"62316":37834,"62317":37844,"62318":37870,"62319":37859,"62320":37845,"62321":37828,"62322":37838,"62323":37824,"62324":37842,"62325":37863,"62326":38269,"62327":38362,"62328":38363,"62329":38625,"62330":38697,"62331":38699,"62332":38700,"62333":38696,"62334":38694,"62369":38835,"62370":38839,"62371":38838,"62372":38877,"62373":38878,"62374":38879,"62375":39004,"62376":39001,"62377":39005,"62378":38999,"62379":39103,"62380":39101,"62381":39099,"62382":39102,"62383":39240,"62384":39239,"62385":39235,"62386":39334,"62387":39335,"62388":39450,"62389":39445,"62390":39461,"62391":39453,"62392":39460,"62393":39451,"62394":39458,"62395":39456,"62396":39463,"62397":39459,"62398":39454,"62399":39452,"62400":39444,"62401":39618,"62402":39691,"62403":39690,"62404":39694,"62405":39692,"62406":39735,"62407":39914,"62408":39915,"62409":39904,"62410":39902,"62411":39908,"62412":39910,"62413":39906,"62414":39920,"62415":39892,"62416":39895,"62417":39916,"62418":39900,"62419":39897,"62420":39909,"62421":39893,"62422":39905,"62423":39898,"62424":40311,"62425":40321,"62426":40330,"62427":40324,"62428":40328,"62429":40305,"62430":40320,"62431":40312,"62432":40326,"62433":40331,"62434":40332,"62435":40317,"62436":40299,"62437":40308,"62438":40309,"62439":40304,"62440":40297,"62441":40325,"62442":40307,"62443":40315,"62444":40322,"62445":40303,"62446":40313,"62447":40319,"62448":40327,"62449":40296,"62450":40596,"62451":40593,"62452":40640,"62453":40700,"62454":40749,"62455":40768,"62456":40769,"62457":40781,"62458":40790,"62459":40791,"62460":40792,"62461":21303,"62462":22194,"62528":22197,"62529":22195,"62530":22755,"62531":23365,"62532":24006,"62533":24007,"62534":24302,"62535":24303,"62536":24512,"62537":24513,"62538":25081,"62539":25879,"62540":25878,"62541":25877,"62542":25875,"62543":26079,"62544":26344,"62545":26339,"62546":26340,"62547":27379,"62548":27376,"62549":27370,"62550":27368,"62551":27385,"62552":27377,"62553":27374,"62554":27375,"62555":28732,"62556":28725,"62557":28719,"62558":28727,"62559":28724,"62560":28721,"62561":28738,"62562":28728,"62563":28735,"62564":28730,"62565":28729,"62566":28736,"62567":28731,"62568":28723,"62569":28737,"62570":29203,"62571":29204,"62572":29352,"62573":29565,"62574":29564,"62575":29882,"62576":30379,"62577":30378,"62578":30398,"62579":30445,"62580":30668,"62581":30670,"62582":30671,"62583":30669,"62584":30706,"62585":31013,"62586":31011,"62587":31015,"62588":31016,"62589":31012,"62590":31017,"62625":31154,"62626":31342,"62627":31340,"62628":31341,"62629":31479,"62630":31817,"62631":31816,"62632":31818,"62633":31815,"62634":31813,"62635":31982,"62636":32379,"62637":32382,"62638":32385,"62639":32384,"62640":32698,"62641":32767,"62642":32889,"62643":33243,"62644":33241,"62645":33291,"62646":33384,"62647":33385,"62648":34338,"62649":34303,"62650":34305,"62651":34302,"62652":34331,"62653":34304,"62654":34294,"62655":34308,"62656":34313,"62657":34309,"62658":34316,"62659":34301,"62660":34841,"62661":34832,"62662":34833,"62663":34839,"62664":34835,"62665":34838,"62666":35171,"62667":35174,"62668":35257,"62669":35319,"62670":35680,"62671":35690,"62672":35677,"62673":35688,"62674":35683,"62675":35685,"62676":35687,"62677":35693,"62678":36270,"62679":36486,"62680":36488,"62681":36484,"62682":36697,"62683":36694,"62684":36695,"62685":36693,"62686":36696,"62687":36698,"62688":37005,"62689":37187,"62690":37185,"62691":37303,"62692":37301,"62693":37298,"62694":37299,"62695":37899,"62696":37907,"62697":37883,"62698":37920,"62699":37903,"62700":37908,"62701":37886,"62702":37909,"62703":37904,"62704":37928,"62705":37913,"62706":37901,"62707":37877,"62708":37888,"62709":37879,"62710":37895,"62711":37902,"62712":37910,"62713":37906,"62714":37882,"62715":37897,"62716":37880,"62717":37898,"62718":37887,"62784":37884,"62785":37900,"62786":37878,"62787":37905,"62788":37894,"62789":38366,"62790":38368,"62791":38367,"62792":38702,"62793":38703,"62794":38841,"62795":38843,"62796":38909,"62797":38910,"62798":39008,"62799":39010,"62800":39011,"62801":39007,"62802":39105,"62803":39106,"62804":39248,"62805":39246,"62806":39257,"62807":39244,"62808":39243,"62809":39251,"62810":39474,"62811":39476,"62812":39473,"62813":39468,"62814":39466,"62815":39478,"62816":39465,"62817":39470,"62818":39480,"62819":39469,"62820":39623,"62821":39626,"62822":39622,"62823":39696,"62824":39698,"62825":39697,"62826":39947,"62827":39944,"62828":39927,"62829":39941,"62830":39954,"62831":39928,"62832":40000,"62833":39943,"62834":39950,"62835":39942,"62836":39959,"62837":39956,"62838":39945,"62839":40351,"62840":40345,"62841":40356,"62842":40349,"62843":40338,"62844":40344,"62845":40336,"62846":40347,"62881":40352,"62882":40340,"62883":40348,"62884":40362,"62885":40343,"62886":40353,"62887":40346,"62888":40354,"62889":40360,"62890":40350,"62891":40355,"62892":40383,"62893":40361,"62894":40342,"62895":40358,"62896":40359,"62897":40601,"62898":40603,"62899":40602,"62900":40677,"62901":40676,"62902":40679,"62903":40678,"62904":40752,"62905":40750,"62906":40795,"62907":40800,"62908":40798,"62909":40797,"62910":40793,"62911":40849,"62912":20794,"62913":20793,"62914":21144,"62915":21143,"62916":22211,"62917":22205,"62918":22206,"62919":23368,"62920":23367,"62921":24011,"62922":24015,"62923":24305,"62924":25085,"62925":25883,"62926":27394,"62927":27388,"62928":27395,"62929":27384,"62930":27392,"62931":28739,"62932":28740,"62933":28746,"62934":28744,"62935":28745,"62936":28741,"62937":28742,"62938":29213,"62939":29210,"62940":29209,"62941":29566,"62942":29975,"62943":30314,"62944":30672,"62945":31021,"62946":31025,"62947":31023,"62948":31828,"62949":31827,"62950":31986,"62951":32394,"62952":32391,"62953":32392,"62954":32395,"62955":32390,"62956":32397,"62957":32589,"62958":32699,"62959":32816,"62960":33245,"62961":34328,"62962":34346,"62963":34342,"62964":34335,"62965":34339,"62966":34332,"62967":34329,"62968":34343,"62969":34350,"62970":34337,"62971":34336,"62972":34345,"62973":34334,"62974":34341,"63040":34857,"63041":34845,"63042":34843,"63043":34848,"63044":34852,"63045":34844,"63046":34859,"63047":34890,"63048":35181,"63049":35177,"63050":35182,"63051":35179,"63052":35322,"63053":35705,"63054":35704,"63055":35653,"63056":35706,"63057":35707,"63058":36112,"63059":36116,"63060":36271,"63061":36494,"63062":36492,"63063":36702,"63064":36699,"63065":36701,"63066":37190,"63067":37188,"63068":37189,"63069":37305,"63070":37951,"63071":37947,"63072":37942,"63073":37929,"63074":37949,"63075":37948,"63076":37936,"63077":37945,"63078":37930,"63079":37943,"63080":37932,"63081":37952,"63082":37937,"63083":38373,"63084":38372,"63085":38371,"63086":38709,"63087":38714,"63088":38847,"63089":38881,"63090":39012,"63091":39113,"63092":39110,"63093":39104,"63094":39256,"63095":39254,"63096":39481,"63097":39485,"63098":39494,"63099":39492,"63100":39490,"63101":39489,"63102":39482,"63137":39487,"63138":39629,"63139":39701,"63140":39703,"63141":39704,"63142":39702,"63143":39738,"63144":39762,"63145":39979,"63146":39965,"63147":39964,"63148":39980,"63149":39971,"63150":39976,"63151":39977,"63152":39972,"63153":39969,"63154":40375,"63155":40374,"63156":40380,"63157":40385,"63158":40391,"63159":40394,"63160":40399,"63161":40382,"63162":40389,"63163":40387,"63164":40379,"63165":40373,"63166":40398,"63167":40377,"63168":40378,"63169":40364,"63170":40392,"63171":40369,"63172":40365,"63173":40396,"63174":40371,"63175":40397,"63176":40370,"63177":40570,"63178":40604,"63179":40683,"63180":40686,"63181":40685,"63182":40731,"63183":40728,"63184":40730,"63185":40753,"63186":40782,"63187":40805,"63188":40804,"63189":40850,"63190":20153,"63191":22214,"63192":22213,"63193":22219,"63194":22897,"63195":23371,"63196":23372,"63197":24021,"63198":24017,"63199":24306,"63200":25889,"63201":25888,"63202":25894,"63203":25890,"63204":27403,"63205":27400,"63206":27401,"63207":27661,"63208":28757,"63209":28758,"63210":28759,"63211":28754,"63212":29214,"63213":29215,"63214":29353,"63215":29567,"63216":29912,"63217":29909,"63218":29913,"63219":29911,"63220":30317,"63221":30381,"63222":31029,"63223":31156,"63224":31344,"63225":31345,"63226":31831,"63227":31836,"63228":31833,"63229":31835,"63230":31834,"63296":31988,"63297":31985,"63298":32401,"63299":32591,"63300":32647,"63301":33246,"63302":33387,"63303":34356,"63304":34357,"63305":34355,"63306":34348,"63307":34354,"63308":34358,"63309":34860,"63310":34856,"63311":34854,"63312":34858,"63313":34853,"63314":35185,"63315":35263,"63316":35262,"63317":35323,"63318":35710,"63319":35716,"63320":35714,"63321":35718,"63322":35717,"63323":35711,"63324":36117,"63325":36501,"63326":36500,"63327":36506,"63328":36498,"63329":36496,"63330":36502,"63331":36503,"63332":36704,"63333":36706,"63334":37191,"63335":37964,"63336":37968,"63337":37962,"63338":37963,"63339":37967,"63340":37959,"63341":37957,"63342":37960,"63343":37961,"63344":37958,"63345":38719,"63346":38883,"63347":39018,"63348":39017,"63349":39115,"63350":39252,"63351":39259,"63352":39502,"63353":39507,"63354":39508,"63355":39500,"63356":39503,"63357":39496,"63358":39498,"63393":39497,"63394":39506,"63395":39504,"63396":39632,"63397":39705,"63398":39723,"63399":39739,"63400":39766,"63401":39765,"63402":40006,"63403":40008,"63404":39999,"63405":40004,"63406":39993,"63407":39987,"63408":40001,"63409":39996,"63410":39991,"63411":39988,"63412":39986,"63413":39997,"63414":39990,"63415":40411,"63416":40402,"63417":40414,"63418":40410,"63419":40395,"63420":40400,"63421":40412,"63422":40401,"63423":40415,"63424":40425,"63425":40409,"63426":40408,"63427":40406,"63428":40437,"63429":40405,"63430":40413,"63431":40630,"63432":40688,"63433":40757,"63434":40755,"63435":40754,"63436":40770,"63437":40811,"63438":40853,"63439":40866,"63440":20797,"63441":21145,"63442":22760,"63443":22759,"63444":22898,"63445":23373,"63446":24024,"63447":34863,"63448":24399,"63449":25089,"63450":25091,"63451":25092,"63452":25897,"63453":25893,"63454":26006,"63455":26347,"63456":27409,"63457":27410,"63458":27407,"63459":27594,"63460":28763,"63461":28762,"63462":29218,"63463":29570,"63464":29569,"63465":29571,"63466":30320,"63467":30676,"63468":31847,"63469":31846,"63470":32405,"63471":33388,"63472":34362,"63473":34368,"63474":34361,"63475":34364,"63476":34353,"63477":34363,"63478":34366,"63479":34864,"63480":34866,"63481":34862,"63482":34867,"63483":35190,"63484":35188,"63485":35187,"63486":35326,"63552":35724,"63553":35726,"63554":35723,"63555":35720,"63556":35909,"63557":36121,"63558":36504,"63559":36708,"63560":36707,"63561":37308,"63562":37986,"63563":37973,"63564":37981,"63565":37975,"63566":37982,"63567":38852,"63568":38853,"63569":38912,"63570":39510,"63571":39513,"63572":39710,"63573":39711,"63574":39712,"63575":40018,"63576":40024,"63577":40016,"63578":40010,"63579":40013,"63580":40011,"63581":40021,"63582":40025,"63583":40012,"63584":40014,"63585":40443,"63586":40439,"63587":40431,"63588":40419,"63589":40427,"63590":40440,"63591":40420,"63592":40438,"63593":40417,"63594":40430,"63595":40422,"63596":40434,"63597":40432,"63598":40418,"63599":40428,"63600":40436,"63601":40435,"63602":40424,"63603":40429,"63604":40642,"63605":40656,"63606":40690,"63607":40691,"63608":40710,"63609":40732,"63610":40760,"63611":40759,"63612":40758,"63613":40771,"63614":40783,"63649":40817,"63650":40816,"63651":40814,"63652":40815,"63653":22227,"63654":22221,"63655":23374,"63656":23661,"63657":25901,"63658":26349,"63659":26350,"63660":27411,"63661":28767,"63662":28769,"63663":28765,"63664":28768,"63665":29219,"63666":29915,"63667":29925,"63668":30677,"63669":31032,"63670":31159,"63671":31158,"63672":31850,"63673":32407,"63674":32649,"63675":33389,"63676":34371,"63677":34872,"63678":34871,"63679":34869,"63680":34891,"63681":35732,"63682":35733,"63683":36510,"63684":36511,"63685":36512,"63686":36509,"63687":37310,"63688":37309,"63689":37314,"63690":37995,"63691":37992,"63692":37993,"63693":38629,"63694":38726,"63695":38723,"63696":38727,"63697":38855,"63698":38885,"63699":39518,"63700":39637,"63701":39769,"63702":40035,"63703":40039,"63704":40038,"63705":40034,"63706":40030,"63707":40032,"63708":40450,"63709":40446,"63710":40455,"63711":40451,"63712":40454,"63713":40453,"63714":40448,"63715":40449,"63716":40457,"63717":40447,"63718":40445,"63719":40452,"63720":40608,"63721":40734,"63722":40774,"63723":40820,"63724":40821,"63725":40822,"63726":22228,"63727":25902,"63728":26040,"63729":27416,"63730":27417,"63731":27415,"63732":27418,"63733":28770,"63734":29222,"63735":29354,"63736":30680,"63737":30681,"63738":31033,"63739":31849,"63740":31851,"63741":31990,"63742":32410,"63808":32408,"63809":32411,"63810":32409,"63811":33248,"63812":33249,"63813":34374,"63814":34375,"63815":34376,"63816":35193,"63817":35194,"63818":35196,"63819":35195,"63820":35327,"63821":35736,"63822":35737,"63823":36517,"63824":36516,"63825":36515,"63826":37998,"63827":37997,"63828":37999,"63829":38001,"63830":38003,"63831":38729,"63832":39026,"63833":39263,"63834":40040,"63835":40046,"63836":40045,"63837":40459,"63838":40461,"63839":40464,"63840":40463,"63841":40466,"63842":40465,"63843":40609,"63844":40693,"63845":40713,"63846":40775,"63847":40824,"63848":40827,"63849":40826,"63850":40825,"63851":22302,"63852":28774,"63853":31855,"63854":34876,"63855":36274,"63856":36518,"63857":37315,"63858":38004,"63859":38008,"63860":38006,"63861":38005,"63862":39520,"63863":40052,"63864":40051,"63865":40049,"63866":40053,"63867":40468,"63868":40467,"63869":40694,"63870":40714,"63905":40868,"63906":28776,"63907":28773,"63908":31991,"63909":34410,"63910":34878,"63911":34877,"63912":34879,"63913":35742,"63914":35996,"63915":36521,"63916":36553,"63917":38731,"63918":39027,"63919":39028,"63920":39116,"63921":39265,"63922":39339,"63923":39524,"63924":39526,"63925":39527,"63926":39716,"63927":40469,"63928":40471,"63929":40776,"63930":25095,"63931":27422,"63932":29223,"63933":34380,"63934":36520,"63935":38018,"63936":38016,"63937":38017,"63938":39529,"63939":39528,"63940":39726,"63941":40473,"63942":29225,"63943":34379,"63944":35743,"63945":38019,"63946":40057,"63947":40631,"63948":30325,"63949":39531,"63950":40058,"63951":40477,"63952":28777,"63953":28778,"63954":40612,"63955":40830,"63956":40777,"63957":40856,"63958":30849,"63959":37561,"63960":35023,"63961":22715,"63962":24658,"63963":31911,"63964":23290,"63965":9556,"63966":9574,"63967":9559,"63968":9568,"63969":9580,"63970":9571,"63971":9562,"63972":9577,"63973":9565,"63974":9554,"63975":9572,"63976":9557,"63977":9566,"63978":9578,"63979":9569,"63980":9560,"63981":9575,"63982":9563,"63983":9555,"63984":9573,"63985":9558,"63986":9567,"63987":9579,"63988":9570,"63989":9561,"63990":9576,"63991":9564,"63992":9553,"63993":9552,"63994":9581,"63995":9582,"63996":9584,"63997":9583,"63998":9619,"64064":57344,"64065":57345,"64066":57346,"64067":57347,"64068":57348,"64069":57349,"64070":57350,"64071":57351,"64072":57352,"64073":57353,"64074":57354,"64075":57355,"64076":57356,"64077":57357,"64078":57358,"64079":57359,"64080":57360,"64081":57361,"64082":57362,"64083":57363,"64084":57364,"64085":57365,"64086":57366,"64087":57367,"64088":57368,"64089":57369,"64090":57370,"64091":57371,"64092":57372,"64093":57373,"64094":57374,"64095":57375,"64096":57376,"64097":57377,"64098":57378,"64099":57379,"64100":29234,"64101":29244,"64102":29286,"64103":29314,"64104":29327,"64105":29343,"64106":29357,"64107":29361,"64108":29368,"64109":29374,"64110":29389,"64111":29403,"64112":29476,"64113":29487,"64114":29496,"64115":29497,"64116":29629,"64117":29646,"64118":29681,"64119":29814,"64120":29858,"64121":29953,"64122":29977,"64123":29987,"64124":30012,"64125":30020,"64126":30025,"64161":30029,"64162":30061,"64163":30082,"64164":30083,"64165":30089,"64166":30124,"64167":30166,"64168":30185,"64169":30272,"64170":30285,"64171":30292,"64172":30312,"64173":30336,"64174":30339,"64175":30352,"64176":30391,"64177":30393,"64178":30477,"64179":30494,"64180":30531,"64181":30744,"64182":30748,"64183":30777,"64184":30780,"64185":30791,"64186":30806,"64187":30842,"64188":30901,"64189":30905,"64190":30918,"64191":30937,"64192":30983,"64193":31024,"64194":31028,"64195":31035,"64196":31104,"64197":31133,"64198":31171,"64199":31201,"64200":31238,"64201":31246,"64202":31299,"64203":31312,"64204":31427,"64205":31442,"64206":31458,"64207":31463,"64208":31480,"64209":31542,"64210":31586,"64211":31596,"64212":31610,"64213":31611,"64214":31642,"64215":31646,"64216":31647,"64217":31650,"64218":31655,"64219":31734,"64220":31762,"64221":31764,"64222":31823,"64223":31830,"64224":31832,"64225":31915,"64226":31994,"64227":32072,"64228":32075,"64229":32119,"64230":32212,"64231":32213,"64232":32214,"64233":32228,"64234":32333,"64235":32349,"64236":32383,"64237":32393,"64238":32398,"64239":32402,"64240":32468,"64241":32497,"64242":32530,"64243":32560,"64244":32625,"64245":32642,"64246":32686,"64247":32710,"64248":32800,"64249":32802,"64250":32805,"64251":32817,"64252":32863,"64253":32872,"64254":32940,"64320":32951,"64321":20890,"64322":21526,"64323":21524,"64324":13535,"64325":19581,"64326":25283,"64327":57508,"64328":57509,"64329":57510,"64330":21707,"64331":57512,"64332":21948,"64333":32950,"64334":20903,"64335":57516,"64336":57517,"64337":57518,"64338":21779,"64339":33318,"64340":57521,"64341":21790,"64342":21982,"64343":25529,"64344":26776,"64345":57526,"64346":21762,"64347":21865,"64348":30132,"64349":25596,"64350":40580,"64351":37418,"64352":57533,"64353":57534,"64354":57535,"64355":35015,"64356":24734,"64357":22053,"64358":28997,"64359":23282,"64360":57541,"64361":21135,"64362":22095,"64363":30611,"64364":34694,"64365":36397,"64366":33206,"64367":13822,"64368":29174,"64369":57550,"64370":34820,"64371":37765,"64372":57553,"64373":57554,"64374":30310,"64375":57556,"64376":40050,"64377":57558,"64378":25294,"64379":57560,"64380":40598,"64381":18825,"64382":31955,"64417":36570,"64418":40619,"64419":25831,"64420":57567,"64421":33450,"64422":26471,"64423":28018,"64424":30982,"64425":31172,"64426":32590,"64427":34798,"64428":57575,"64429":33726,"64430":34351,"64431":35237,"64432":17935,"64433":57580,"64434":39112,"64435":39232,"64436":39245,"64437":39436,"64438":39639,"64439":40600,"64440":40742,"64441":57588,"64442":20227,"64443":57590,"64444":20281,"64445":20274,"64446":20395,"64447":20566,"64448":57595,"64449":20526,"64450":20646,"64451":20697,"64452":20750,"64453":20717,"64454":20737,"64455":20980,"64456":21023,"64457":21088,"64458":21079,"64459":21146,"64460":21201,"64461":21216,"64462":21217,"64463":20947,"64464":20959,"64465":30022,"64466":20990,"64467":21298,"64468":21292,"64469":21299,"64470":21419,"64471":21418,"64472":40846,"64473":21609,"64474":21660,"64475":21466,"64476":27338,"64477":21875,"64478":57625,"64479":13782,"64480":57627,"64481":22033,"64482":22093,"64483":57630,"64484":22100,"64485":13811,"64486":57633,"64487":22342,"64488":22394,"64489":22375,"64490":22586,"64491":22502,"64492":22493,"64493":22592,"64494":57641,"64495":22566,"64496":22748,"64497":22967,"64498":23001,"64499":23584,"64500":57647,"64501":23761,"64502":23785,"64503":23878,"64504":23950,"64505":57652,"64506":24053,"64507":24075,"64508":24082,"64509":24110,"64510":24158,"64576":57658,"64577":24397,"64578":31357,"64579":23491,"64580":31419,"64581":57663,"64582":57664,"64583":24484,"64584":24506,"64585":24508,"64586":57668,"64587":24695,"64588":24740,"64589":24755,"64590":24829,"64591":24880,"64592":57674,"64593":24988,"64594":24921,"64595":24957,"64596":24924,"64597":25471,"64598":25058,"64599":28885,"64600":25145,"64601":25192,"64602":25221,"64603":25218,"64604":25254,"64605":25301,"64606":25444,"64607":25397,"64608":25744,"64609":14940,"64610":26184,"64611":26215,"64612":26398,"64613":26627,"64614":26540,"64615":26617,"64616":26806,"64617":26924,"64618":26881,"64619":26880,"64620":26826,"64621":26995,"64622":27008,"64623":26942,"64624":57706,"64625":27058,"64626":27072,"64627":27018,"64628":27130,"64629":27113,"64630":27314,"64631":27218,"64632":27293,"64633":27421,"64634":27474,"64635":27642,"64636":15569,"64637":27854,"64638":28239,"64673":28089,"64674":28484,"64675":57723,"64676":28634,"64677":28801,"64678":31180,"64679":28980,"64680":15820,"64681":29046,"64682":57730,"64683":57731,"64684":29205,"64685":29264,"64686":29319,"64687":29484,"64688":29362,"64689":29410,"64690":29442,"64691":29512,"64692":29480,"64693":29519,"64694":29553,"64695":25989,"64696":57744,"64697":29789,"64698":29800,"64699":29982,"64700":30035,"64701":30074,"64702":30369,"64703":30412,"64704":30500,"64705":30507,"64706":16485,"64707":30803,"64708":30931,"64709":30936,"64710":40318,"64711":30895,"64712":57760,"64713":24898,"64714":31145,"64715":39994,"64716":31188,"64717":57765,"64718":31277,"64719":31294,"64720":31305,"64721":31453,"64722":31450,"64723":30147,"64724":30215,"64725":30210,"64726":57774,"64727":30311,"64728":30319,"64729":22048,"64730":35431,"64731":40727,"64732":31519,"64733":31634,"64734":31651,"64735":31695,"64736":57784,"64737":31740,"64738":31810,"64739":31825,"64740":31837,"64741":31856,"64742":31870,"64743":31878,"64744":31875,"64745":31916,"64746":31943,"64747":31938,"64748":57796,"64749":31962,"64750":57798,"64751":32077,"64752":32090,"64753":32245,"64754":32295,"64755":32366,"64756":40597,"64757":21107,"64758":32797,"64759":32866,"64760":32867,"64761":32870,"64762":32859,"64763":32934,"64764":33027,"64765":40577,"64766":33224,"64832":57815,"64833":36768,"64834":33270,"64835":33306,"64836":57819,"64837":34673,"64838":34729,"64839":34700,"64840":40606,"64841":34753,"64842":40476,"64843":57826,"64844":34774,"64845":34805,"64846":34831,"64847":34840,"64848":34861,"64849":34882,"64850":34885,"64851":39989,"64852":34926,"64853":34986,"64854":34976,"64855":25245,"64856":35139,"64857":35149,"64858":29042,"64859":34910,"64860":57843,"64861":33533,"64862":17591,"64863":33488,"64864":33669,"64865":40194,"64866":40809,"64867":33824,"64868":57851,"64869":34010,"64870":33965,"64871":17659,"64872":34123,"64873":57856,"64874":34306,"64875":34320,"64876":25553,"64877":35209,"64878":35210,"64879":35220,"64880":40005,"64881":35260,"64882":35454,"64883":35401,"64884":35596,"64885":35651,"64886":35713,"64887":35660,"64888":57871,"64889":36013,"64890":36075,"64891":36087,"64892":36108,"64893":36226,"64894":36262,"64929":36308,"64930":36392,"64931":36431,"64932":36471,"64933":36469,"64934":36519,"64935":36633,"64936":57885,"64937":36700,"64938":40260,"64939":37060,"64940":37201,"64941":57890,"64942":37212,"64943":37209,"64944":37223,"64945":37244,"64946":37262,"64947":37307,"64948":40616,"64949":36950,"64950":36940,"64951":37374,"64952":37474,"64953":37566,"64954":37739,"64955":37742,"64956":37818,"64957":37927,"64958":38295,"64959":38311,"64960":57909,"64961":38456,"64962":57911,"64963":38531,"64964":38550,"64965":38529,"64966":38589,"64967":38659,"64968":38689,"64969":38705,"64970":38751,"64971":38815,"64972":38836,"64973":38840,"64974":38842,"64975":38846,"64976":38856,"64977":40639,"64978":38943,"64979":38958,"64980":40869,"64981":38983,"64982":38987,"64983":39014,"64984":39020,"64985":39092,"64986":40794,"64987":39132,"64988":39142,"64989":39234,"64990":39225,"64991":39227,"64992":40787,"64993":39242,"64994":40773,"64995":19326,"64996":39386,"64997":31432,"64998":39610,"64999":39613,"65000":40706,"65001":39722,"65002":57951,"65003":39725,"65004":39650,"65005":39682,"65006":39679,"65007":19463,"65008":39689,"65009":19460,"65010":19515,"65011":39823,"65012":39837,"65013":39856,"65014":39948,"65015":39957,"65016":39946,"65017":39935,"65018":39982,"65019":33000,"65020":33001,"65021":33004,"65022":33038,"65088":27705,"65089":20074,"65090":38465,"65091":22770,"65092":31074,"65093":26658,"65094":57978,"65095":57979,"65096":33031,"65097":22487,"65098":17642,"65099":25653,"65100":34100,"65101":16607,"65102":57986,"65103":26906,"65104":39938,"65105":30129,"65106":33747,"65107":29041,"65108":27147,"65109":57993,"65110":27258,"65111":39668,"65112":57996,"65113":57997,"65114":30649,"65115":25904,"65116":28054,"65117":22071,"65118":26405,"65119":27179,"65120":32093,"65121":36961,"65122":20120,"65123":31910,"65124":31545,"65125":58009,"65126":22901,"65127":14023,"65128":28799,"65129":58013,"65130":28299,"65131":58015,"65132":58016,"65133":38749,"65134":37584,"65135":22356,"65136":58020,"65137":16089,"65138":58022,"65139":58023,"65140":24985,"65141":29792,"65142":28991,"65143":31022,"65144":23190,"65145":37704,"65146":26254,"65147":20477,"65148":37697,"65149":13908,"65150":23925,"65185":28702,"65186":25979,"65187":28813,"65188":24269,"65189":58039,"65190":24743,"65191":31408,"65192":24419,"65193":58043,"65194":29687,"65195":58045,"65196":29800,"65197":30132,"65198":58048,"65199":39785,"65200":189,"65201":8531,"65202":8532,"65203":188,"65204":190,"65205":8533,"65206":8534,"65207":8535,"65208":8536,"65209":8537,"65210":8538,"65211":34450,"65212":34464,"65213":34477,"65214":34482,"65215":34725,"65216":34737,"65217":8539,"65218":8540,"65219":8541,"65220":8542,"65221":34778,"65222":34895,"65223":34912,"65224":34951,"65225":34959,"65226":34960,"65227":35046,"65228":35071,"65229":35072,"65230":35108,"65231":35143,"65232":35156,"65233":35173,"65234":35200,"65235":35217,"65236":35356,"65237":35369,"65238":35371,"65239":35384,"65240":35389,"65241":8978,"65242":35472,"65243":35476,"65244":35484,"65245":35497,"65246":35503,"65247":35508,"65248":35562,"65249":35615,"65250":8240,"65251":35647,"65252":35661,"65253":35678,"65254":35682,"65255":35689,"65256":35739,"65257":35921,"65258":35995,"65259":35999,"65260":36052,"65261":36054,"65262":33042,"65263":33073,"65264":33078,"65265":33119,"65266":33133,"65267":33149,"65268":33171,"65269":33194,"65270":33208,"65271":33217,"65272":33321,"65273":33325,"65274":33326,"65275":33342,"65276":33378,"65277":33386,"65278":33416,"NaN":null} \ No newline at end of file diff --git a/node_modules/grunt/node_modules/iconv-lite/encodings/table/gbk.js b/node_modules/grunt/node_modules/iconv-lite/encodings/table/gbk.js new file mode 100644 index 000000000..c464623e5 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/encodings/table/gbk.js @@ -0,0 +1 @@ +module.exports={33088:19970,33089:19972,33090:19973,33091:19974,33092:19983,33093:19986,33094:19991,33095:19999,33096:20000,33097:20001,33098:20003,33099:20006,33100:20009,33101:20014,33102:20015,33103:20017,33104:20019,33105:20021,33106:20023,33107:20028,33108:20032,33109:20033,33110:20034,33111:20036,33112:20038,33113:20042,33114:20049,33115:20053,33116:20055,33117:20058,33118:20059,33119:20066,33120:20067,33121:20068,33122:20069,33123:20071,33124:20072,33125:20074,33126:20075,33127:20076,33128:20077,33129:20078,33130:20079,33131:20082,33132:20084,33133:20085,33134:20086,33135:20087,33136:20088,33137:20089,33138:20090,33139:20091,33140:20092,33141:20093,33142:20095,33143:20096,33144:20097,33145:20098,33146:20099,33147:20100,33148:20101,33149:20103,33150:20106,33152:20112,33153:20118,33154:20119,33155:20121,33156:20124,33157:20125,33158:20126,33159:20131,33160:20138,33161:20143,33162:20144,33163:20145,33164:20148,33165:20150,33166:20151,33167:20152,33168:20153,33169:20156,33170:20157,33171:20158,33172:20168,33173:20172,33174:20175,33175:20176,33176:20178,33177:20186,33178:20187,33179:20188,33180:20192,33181:20194,33182:20198,33183:20199,33184:20201,33185:20205,33186:20206,33187:20207,33188:20209,33189:20212,33190:20216,33191:20217,33192:20218,33193:20220,33194:20222,33195:20224,33196:20226,33197:20227,33198:20228,33199:20229,33200:20230,33201:20231,33202:20232,33203:20235,33204:20236,33205:20242,33206:20243,33207:20244,33208:20245,33209:20246,33210:20252,33211:20253,33212:20257,33213:20259,33214:20264,33215:20265,33216:20268,33217:20269,33218:20270,33219:20273,33220:20275,33221:20277,33222:20279,33223:20281,33224:20283,33225:20286,33226:20287,33227:20288,33228:20289,33229:20290,33230:20292,33231:20293,33232:20295,33233:20296,33234:20297,33235:20298,33236:20299,33237:20300,33238:20306,33239:20308,33240:20310,33241:20321,33242:20322,33243:20326,33244:20328,33245:20330,33246:20331,33247:20333,33248:20334,33249:20337,33250:20338,33251:20341,33252:20343,33253:20344,33254:20345,33255:20346,33256:20349,33257:20352,33258:20353,33259:20354,33260:20357,33261:20358,33262:20359,33263:20362,33264:20364,33265:20366,33266:20368,33267:20370,33268:20371,33269:20373,33270:20374,33271:20376,33272:20377,33273:20378,33274:20380,33275:20382,33276:20383,33277:20385,33278:20386,33344:20388,33345:20395,33346:20397,33347:20400,33348:20401,33349:20402,33350:20403,33351:20404,33352:20406,33353:20407,33354:20408,33355:20409,33356:20410,33357:20411,33358:20412,33359:20413,33360:20414,33361:20416,33362:20417,33363:20418,33364:20422,33365:20423,33366:20424,33367:20425,33368:20427,33369:20428,33370:20429,33371:20434,33372:20435,33373:20436,33374:20437,33375:20438,33376:20441,33377:20443,33378:20448,33379:20450,33380:20452,33381:20453,33382:20455,33383:20459,33384:20460,33385:20464,33386:20466,33387:20468,33388:20469,33389:20470,33390:20471,33391:20473,33392:20475,33393:20476,33394:20477,33395:20479,33396:20480,33397:20481,33398:20482,33399:20483,33400:20484,33401:20485,33402:20486,33403:20487,33404:20488,33405:20489,33406:20490,33408:20491,33409:20494,33410:20496,33411:20497,33412:20499,33413:20501,33414:20502,33415:20503,33416:20507,33417:20509,33418:20510,33419:20512,33420:20514,33421:20515,33422:20516,33423:20519,33424:20523,33425:20527,33426:20528,33427:20529,33428:20530,33429:20531,33430:20532,33431:20533,33432:20534,33433:20535,33434:20536,33435:20537,33436:20539,33437:20541,33438:20543,33439:20544,33440:20545,33441:20546,33442:20548,33443:20549,33444:20550,33445:20553,33446:20554,33447:20555,33448:20557,33449:20560,33450:20561,33451:20562,33452:20563,33453:20564,33454:20566,33455:20567,33456:20568,33457:20569,33458:20571,33459:20573,33460:20574,33461:20575,33462:20576,33463:20577,33464:20578,33465:20579,33466:20580,33467:20582,33468:20583,33469:20584,33470:20585,33471:20586,33472:20587,33473:20589,33474:20590,33475:20591,33476:20592,33477:20593,33478:20594,33479:20595,33480:20596,33481:20597,33482:20600,33483:20601,33484:20602,33485:20604,33486:20605,33487:20609,33488:20610,33489:20611,33490:20612,33491:20614,33492:20615,33493:20617,33494:20618,33495:20619,33496:20620,33497:20622,33498:20623,33499:20624,33500:20625,33501:20626,33502:20627,33503:20628,33504:20629,33505:20630,33506:20631,33507:20632,33508:20633,33509:20634,33510:20635,33511:20636,33512:20637,33513:20638,33514:20639,33515:20640,33516:20641,33517:20642,33518:20644,33519:20646,33520:20650,33521:20651,33522:20653,33523:20654,33524:20655,33525:20656,33526:20657,33527:20659,33528:20660,33529:20661,33530:20662,33531:20663,33532:20664,33533:20665,33534:20668,33600:20669,33601:20670,33602:20671,33603:20672,33604:20673,33605:20674,33606:20675,33607:20676,33608:20677,33609:20678,33610:20679,33611:20680,33612:20681,33613:20682,33614:20683,33615:20684,33616:20685,33617:20686,33618:20688,33619:20689,33620:20690,33621:20691,33622:20692,33623:20693,33624:20695,33625:20696,33626:20697,33627:20699,33628:20700,33629:20701,33630:20702,33631:20703,33632:20704,33633:20705,33634:20706,33635:20707,33636:20708,33637:20709,33638:20712,33639:20713,33640:20714,33641:20715,33642:20719,33643:20720,33644:20721,33645:20722,33646:20724,33647:20726,33648:20727,33649:20728,33650:20729,33651:20730,33652:20732,33653:20733,33654:20734,33655:20735,33656:20736,33657:20737,33658:20738,33659:20739,33660:20740,33661:20741,33662:20744,33664:20745,33665:20746,33666:20748,33667:20749,33668:20750,33669:20751,33670:20752,33671:20753,33672:20755,33673:20756,33674:20757,33675:20758,33676:20759,33677:20760,33678:20761,33679:20762,33680:20763,33681:20764,33682:20765,33683:20766,33684:20767,33685:20768,33686:20770,33687:20771,33688:20772,33689:20773,33690:20774,33691:20775,33692:20776,33693:20777,33694:20778,33695:20779,33696:20780,33697:20781,33698:20782,33699:20783,33700:20784,33701:20785,33702:20786,33703:20787,33704:20788,33705:20789,33706:20790,33707:20791,33708:20792,33709:20793,33710:20794,33711:20795,33712:20796,33713:20797,33714:20798,33715:20802,33716:20807,33717:20810,33718:20812,33719:20814,33720:20815,33721:20816,33722:20818,33723:20819,33724:20823,33725:20824,33726:20825,33727:20827,33728:20829,33729:20830,33730:20831,33731:20832,33732:20833,33733:20835,33734:20836,33735:20838,33736:20839,33737:20841,33738:20842,33739:20847,33740:20850,33741:20858,33742:20862,33743:20863,33744:20867,33745:20868,33746:20870,33747:20871,33748:20874,33749:20875,33750:20878,33751:20879,33752:20880,33753:20881,33754:20883,33755:20884,33756:20888,33757:20890,33758:20893,33759:20894,33760:20895,33761:20897,33762:20899,33763:20902,33764:20903,33765:20904,33766:20905,33767:20906,33768:20909,33769:20910,33770:20916,33771:20920,33772:20921,33773:20922,33774:20926,33775:20927,33776:20929,33777:20930,33778:20931,33779:20933,33780:20936,33781:20938,33782:20941,33783:20942,33784:20944,33785:20946,33786:20947,33787:20948,33788:20949,33789:20950,33790:20951,33856:20952,33857:20953,33858:20954,33859:20956,33860:20958,33861:20959,33862:20962,33863:20963,33864:20965,33865:20966,33866:20967,33867:20968,33868:20969,33869:20970,33870:20972,33871:20974,33872:20977,33873:20978,33874:20980,33875:20983,33876:20990,33877:20996,33878:20997,33879:21001,33880:21003,33881:21004,33882:21007,33883:21008,33884:21011,33885:21012,33886:21013,33887:21020,33888:21022,33889:21023,33890:21025,33891:21026,33892:21027,33893:21029,33894:21030,33895:21031,33896:21034,33897:21036,33898:21039,33899:21041,33900:21042,33901:21044,33902:21045,33903:21052,33904:21054,33905:21060,33906:21061,33907:21062,33908:21063,33909:21064,33910:21065,33911:21067,33912:21070,33913:21071,33914:21074,33915:21075,33916:21077,33917:21079,33918:21080,33920:21081,33921:21082,33922:21083,33923:21085,33924:21087,33925:21088,33926:21090,33927:21091,33928:21092,33929:21094,33930:21096,33931:21099,33932:21100,33933:21101,33934:21102,33935:21104,33936:21105,33937:21107,33938:21108,33939:21109,33940:21110,33941:21111,33942:21112,33943:21113,33944:21114,33945:21115,33946:21116,33947:21118,33948:21120,33949:21123,33950:21124,33951:21125,33952:21126,33953:21127,33954:21129,33955:21130,33956:21131,33957:21132,33958:21133,33959:21134,33960:21135,33961:21137,33962:21138,33963:21140,33964:21141,33965:21142,33966:21143,33967:21144,33968:21145,33969:21146,33970:21148,33971:21156,33972:21157,33973:21158,33974:21159,33975:21166,33976:21167,33977:21168,33978:21172,33979:21173,33980:21174,33981:21175,33982:21176,33983:21177,33984:21178,33985:21179,33986:21180,33987:21181,33988:21184,33989:21185,33990:21186,33991:21188,33992:21189,33993:21190,33994:21192,33995:21194,33996:21196,33997:21197,33998:21198,33999:21199,34000:21201,34001:21203,34002:21204,34003:21205,34004:21207,34005:21209,34006:21210,34007:21211,34008:21212,34009:21213,34010:21214,34011:21216,34012:21217,34013:21218,34014:21219,34015:21221,34016:21222,34017:21223,34018:21224,34019:21225,34020:21226,34021:21227,34022:21228,34023:21229,34024:21230,34025:21231,34026:21233,34027:21234,34028:21235,34029:21236,34030:21237,34031:21238,34032:21239,34033:21240,34034:21243,34035:21244,34036:21245,34037:21249,34038:21250,34039:21251,34040:21252,34041:21255,34042:21257,34043:21258,34044:21259,34045:21260,34046:21262,34112:21265,34113:21266,34114:21267,34115:21268,34116:21272,34117:21275,34118:21276,34119:21278,34120:21279,34121:21282,34122:21284,34123:21285,34124:21287,34125:21288,34126:21289,34127:21291,34128:21292,34129:21293,34130:21295,34131:21296,34132:21297,34133:21298,34134:21299,34135:21300,34136:21301,34137:21302,34138:21303,34139:21304,34140:21308,34141:21309,34142:21312,34143:21314,34144:21316,34145:21318,34146:21323,34147:21324,34148:21325,34149:21328,34150:21332,34151:21336,34152:21337,34153:21339,34154:21341,34155:21349,34156:21352,34157:21354,34158:21356,34159:21357,34160:21362,34161:21366,34162:21369,34163:21371,34164:21372,34165:21373,34166:21374,34167:21376,34168:21377,34169:21379,34170:21383,34171:21384,34172:21386,34173:21390,34174:21391,34176:21392,34177:21393,34178:21394,34179:21395,34180:21396,34181:21398,34182:21399,34183:21401,34184:21403,34185:21404,34186:21406,34187:21408,34188:21409,34189:21412,34190:21415,34191:21418,34192:21419,34193:21420,34194:21421,34195:21423,34196:21424,34197:21425,34198:21426,34199:21427,34200:21428,34201:21429,34202:21431,34203:21432,34204:21433,34205:21434,34206:21436,34207:21437,34208:21438,34209:21440,34210:21443,34211:21444,34212:21445,34213:21446,34214:21447,34215:21454,34216:21455,34217:21456,34218:21458,34219:21459,34220:21461,34221:21466,34222:21468,34223:21469,34224:21470,34225:21473,34226:21474,34227:21479,34228:21492,34229:21498,34230:21502,34231:21503,34232:21504,34233:21506,34234:21509,34235:21511,34236:21515,34237:21524,34238:21528,34239:21529,34240:21530,34241:21532,34242:21538,34243:21540,34244:21541,34245:21546,34246:21552,34247:21555,34248:21558,34249:21559,34250:21562,34251:21565,34252:21567,34253:21569,34254:21570,34255:21572,34256:21573,34257:21575,34258:21577,34259:21580,34260:21581,34261:21582,34262:21583,34263:21585,34264:21594,34265:21597,34266:21598,34267:21599,34268:21600,34269:21601,34270:21603,34271:21605,34272:21607,34273:21609,34274:21610,34275:21611,34276:21612,34277:21613,34278:21614,34279:21615,34280:21616,34281:21620,34282:21625,34283:21626,34284:21630,34285:21631,34286:21633,34287:21635,34288:21637,34289:21639,34290:21640,34291:21641,34292:21642,34293:21645,34294:21649,34295:21651,34296:21655,34297:21656,34298:21660,34299:21662,34300:21663,34301:21664,34302:21665,34368:21666,34369:21669,34370:21678,34371:21680,34372:21682,34373:21685,34374:21686,34375:21687,34376:21689,34377:21690,34378:21692,34379:21694,34380:21699,34381:21701,34382:21706,34383:21707,34384:21718,34385:21720,34386:21723,34387:21728,34388:21729,34389:21730,34390:21731,34391:21732,34392:21739,34393:21740,34394:21743,34395:21744,34396:21745,34397:21748,34398:21749,34399:21750,34400:21751,34401:21752,34402:21753,34403:21755,34404:21758,34405:21760,34406:21762,34407:21763,34408:21764,34409:21765,34410:21768,34411:21770,34412:21771,34413:21772,34414:21773,34415:21774,34416:21778,34417:21779,34418:21781,34419:21782,34420:21783,34421:21784,34422:21785,34423:21786,34424:21788,34425:21789,34426:21790,34427:21791,34428:21793,34429:21797,34430:21798,34432:21800,34433:21801,34434:21803,34435:21805,34436:21810,34437:21812,34438:21813,34439:21814,34440:21816,34441:21817,34442:21818,34443:21819,34444:21821,34445:21824,34446:21826,34447:21829,34448:21831,34449:21832,34450:21835,34451:21836,34452:21837,34453:21838,34454:21839,34455:21841,34456:21842,34457:21843,34458:21844,34459:21847,34460:21848,34461:21849,34462:21850,34463:21851,34464:21853,34465:21854,34466:21855,34467:21856,34468:21858,34469:21859,34470:21864,34471:21865,34472:21867,34473:21871,34474:21872,34475:21873,34476:21874,34477:21875,34478:21876,34479:21881,34480:21882,34481:21885,34482:21887,34483:21893,34484:21894,34485:21900,34486:21901,34487:21902,34488:21904,34489:21906,34490:21907,34491:21909,34492:21910,34493:21911,34494:21914,34495:21915,34496:21918,34497:21920,34498:21921,34499:21922,34500:21923,34501:21924,34502:21925,34503:21926,34504:21928,34505:21929,34506:21930,34507:21931,34508:21932,34509:21933,34510:21934,34511:21935,34512:21936,34513:21938,34514:21940,34515:21942,34516:21944,34517:21946,34518:21948,34519:21951,34520:21952,34521:21953,34522:21954,34523:21955,34524:21958,34525:21959,34526:21960,34527:21962,34528:21963,34529:21966,34530:21967,34531:21968,34532:21973,34533:21975,34534:21976,34535:21977,34536:21978,34537:21979,34538:21982,34539:21984,34540:21986,34541:21991,34542:21993,34543:21997,34544:21998,34545:22000,34546:22001,34547:22004,34548:22006,34549:22008,34550:22009,34551:22010,34552:22011,34553:22012,34554:22015,34555:22018,34556:22019,34557:22020,34558:22021,34624:22022,34625:22023,34626:22026,34627:22027,34628:22029,34629:22032,34630:22033,34631:22034,34632:22035,34633:22036,34634:22037,34635:22038,34636:22039,34637:22041,34638:22042,34639:22044,34640:22045,34641:22048,34642:22049,34643:22050,34644:22053,34645:22054,34646:22056,34647:22057,34648:22058,34649:22059,34650:22062,34651:22063,34652:22064,34653:22067,34654:22069,34655:22071,34656:22072,34657:22074,34658:22076,34659:22077,34660:22078,34661:22080,34662:22081,34663:22082,34664:22083,34665:22084,34666:22085,34667:22086,34668:22087,34669:22088,34670:22089,34671:22090,34672:22091,34673:22095,34674:22096,34675:22097,34676:22098,34677:22099,34678:22101,34679:22102,34680:22106,34681:22107,34682:22109,34683:22110,34684:22111,34685:22112,34686:22113,34688:22115,34689:22117,34690:22118,34691:22119,34692:22125,34693:22126,34694:22127,34695:22128,34696:22130,34697:22131,34698:22132,34699:22133,34700:22135,34701:22136,34702:22137,34703:22138,34704:22141,34705:22142,34706:22143,34707:22144,34708:22145,34709:22146,34710:22147,34711:22148,34712:22151,34713:22152,34714:22153,34715:22154,34716:22155,34717:22156,34718:22157,34719:22160,34720:22161,34721:22162,34722:22164,34723:22165,34724:22166,34725:22167,34726:22168,34727:22169,34728:22170,34729:22171,34730:22172,34731:22173,34732:22174,34733:22175,34734:22176,34735:22177,34736:22178,34737:22180,34738:22181,34739:22182,34740:22183,34741:22184,34742:22185,34743:22186,34744:22187,34745:22188,34746:22189,34747:22190,34748:22192,34749:22193,34750:22194,34751:22195,34752:22196,34753:22197,34754:22198,34755:22200,34756:22201,34757:22202,34758:22203,34759:22205,34760:22206,34761:22207,34762:22208,34763:22209,34764:22210,34765:22211,34766:22212,34767:22213,34768:22214,34769:22215,34770:22216,34771:22217,34772:22219,34773:22220,34774:22221,34775:22222,34776:22223,34777:22224,34778:22225,34779:22226,34780:22227,34781:22229,34782:22230,34783:22232,34784:22233,34785:22236,34786:22243,34787:22245,34788:22246,34789:22247,34790:22248,34791:22249,34792:22250,34793:22252,34794:22254,34795:22255,34796:22258,34797:22259,34798:22262,34799:22263,34800:22264,34801:22267,34802:22268,34803:22272,34804:22273,34805:22274,34806:22277,34807:22279,34808:22283,34809:22284,34810:22285,34811:22286,34812:22287,34813:22288,34814:22289,34880:22290,34881:22291,34882:22292,34883:22293,34884:22294,34885:22295,34886:22296,34887:22297,34888:22298,34889:22299,34890:22301,34891:22302,34892:22304,34893:22305,34894:22306,34895:22308,34896:22309,34897:22310,34898:22311,34899:22315,34900:22321,34901:22322,34902:22324,34903:22325,34904:22326,34905:22327,34906:22328,34907:22332,34908:22333,34909:22335,34910:22337,34911:22339,34912:22340,34913:22341,34914:22342,34915:22344,34916:22345,34917:22347,34918:22354,34919:22355,34920:22356,34921:22357,34922:22358,34923:22360,34924:22361,34925:22370,34926:22371,34927:22373,34928:22375,34929:22380,34930:22382,34931:22384,34932:22385,34933:22386,34934:22388,34935:22389,34936:22392,34937:22393,34938:22394,34939:22397,34940:22398,34941:22399,34942:22400,34944:22401,34945:22407,34946:22408,34947:22409,34948:22410,34949:22413,34950:22414,34951:22415,34952:22416,34953:22417,34954:22420,34955:22421,34956:22422,34957:22423,34958:22424,34959:22425,34960:22426,34961:22428,34962:22429,34963:22430,34964:22431,34965:22437,34966:22440,34967:22442,34968:22444,34969:22447,34970:22448,34971:22449,34972:22451,34973:22453,34974:22454,34975:22455,34976:22457,34977:22458,34978:22459,34979:22460,34980:22461,34981:22462,34982:22463,34983:22464,34984:22465,34985:22468,34986:22469,34987:22470,34988:22471,34989:22472,34990:22473,34991:22474,34992:22476,34993:22477,34994:22480,34995:22481,34996:22483,34997:22486,34998:22487,34999:22491,35000:22492,35001:22494,35002:22497,35003:22498,35004:22499,35005:22501,35006:22502,35007:22503,35008:22504,35009:22505,35010:22506,35011:22507,35012:22508,35013:22510,35014:22512,35015:22513,35016:22514,35017:22515,35018:22517,35019:22518,35020:22519,35021:22523,35022:22524,35023:22526,35024:22527,35025:22529,35026:22531,35027:22532,35028:22533,35029:22536,35030:22537,35031:22538,35032:22540,35033:22542,35034:22543,35035:22544,35036:22546,35037:22547,35038:22548,35039:22550,35040:22551,35041:22552,35042:22554,35043:22555,35044:22556,35045:22557,35046:22559,35047:22562,35048:22563,35049:22565,35050:22566,35051:22567,35052:22568,35053:22569,35054:22571,35055:22572,35056:22573,35057:22574,35058:22575,35059:22577,35060:22578,35061:22579,35062:22580,35063:22582,35064:22583,35065:22584,35066:22585,35067:22586,35068:22587,35069:22588,35070:22589,35136:22590,35137:22591,35138:22592,35139:22593,35140:22594,35141:22595,35142:22597,35143:22598,35144:22599,35145:22600,35146:22601,35147:22602,35148:22603,35149:22606,35150:22607,35151:22608,35152:22610,35153:22611,35154:22613,35155:22614,35156:22615,35157:22617,35158:22618,35159:22619,35160:22620,35161:22621,35162:22623,35163:22624,35164:22625,35165:22626,35166:22627,35167:22628,35168:22630,35169:22631,35170:22632,35171:22633,35172:22634,35173:22637,35174:22638,35175:22639,35176:22640,35177:22641,35178:22642,35179:22643,35180:22644,35181:22645,35182:22646,35183:22647,35184:22648,35185:22649,35186:22650,35187:22651,35188:22652,35189:22653,35190:22655,35191:22658,35192:22660,35193:22662,35194:22663,35195:22664,35196:22666,35197:22667,35198:22668,35200:22669,35201:22670,35202:22671,35203:22672,35204:22673,35205:22676,35206:22677,35207:22678,35208:22679,35209:22680,35210:22683,35211:22684,35212:22685,35213:22688,35214:22689,35215:22690,35216:22691,35217:22692,35218:22693,35219:22694,35220:22695,35221:22698,35222:22699,35223:22700,35224:22701,35225:22702,35226:22703,35227:22704,35228:22705,35229:22706,35230:22707,35231:22708,35232:22709,35233:22710,35234:22711,35235:22712,35236:22713,35237:22714,35238:22715,35239:22717,35240:22718,35241:22719,35242:22720,35243:22722,35244:22723,35245:22724,35246:22726,35247:22727,35248:22728,35249:22729,35250:22730,35251:22731,35252:22732,35253:22733,35254:22734,35255:22735,35256:22736,35257:22738,35258:22739,35259:22740,35260:22742,35261:22743,35262:22744,35263:22745,35264:22746,35265:22747,35266:22748,35267:22749,35268:22750,35269:22751,35270:22752,35271:22753,35272:22754,35273:22755,35274:22757,35275:22758,35276:22759,35277:22760,35278:22761,35279:22762,35280:22765,35281:22767,35282:22769,35283:22770,35284:22772,35285:22773,35286:22775,35287:22776,35288:22778,35289:22779,35290:22780,35291:22781,35292:22782,35293:22783,35294:22784,35295:22785,35296:22787,35297:22789,35298:22790,35299:22792,35300:22793,35301:22794,35302:22795,35303:22796,35304:22798,35305:22800,35306:22801,35307:22802,35308:22803,35309:22807,35310:22808,35311:22811,35312:22813,35313:22814,35314:22816,35315:22817,35316:22818,35317:22819,35318:22822,35319:22824,35320:22828,35321:22832,35322:22834,35323:22835,35324:22837,35325:22838,35326:22843,35392:22845,35393:22846,35394:22847,35395:22848,35396:22851,35397:22853,35398:22854,35399:22858,35400:22860,35401:22861,35402:22864,35403:22866,35404:22867,35405:22873,35406:22875,35407:22876,35408:22877,35409:22878,35410:22879,35411:22881,35412:22883,35413:22884,35414:22886,35415:22887,35416:22888,35417:22889,35418:22890,35419:22891,35420:22892,35421:22893,35422:22894,35423:22895,35424:22896,35425:22897,35426:22898,35427:22901,35428:22903,35429:22906,35430:22907,35431:22908,35432:22910,35433:22911,35434:22912,35435:22917,35436:22921,35437:22923,35438:22924,35439:22926,35440:22927,35441:22928,35442:22929,35443:22932,35444:22933,35445:22936,35446:22938,35447:22939,35448:22940,35449:22941,35450:22943,35451:22944,35452:22945,35453:22946,35454:22950,35456:22951,35457:22956,35458:22957,35459:22960,35460:22961,35461:22963,35462:22964,35463:22965,35464:22966,35465:22967,35466:22968,35467:22970,35468:22972,35469:22973,35470:22975,35471:22976,35472:22977,35473:22978,35474:22979,35475:22980,35476:22981,35477:22983,35478:22984,35479:22985,35480:22988,35481:22989,35482:22990,35483:22991,35484:22997,35485:22998,35486:23001,35487:23003,35488:23006,35489:23007,35490:23008,35491:23009,35492:23010,35493:23012,35494:23014,35495:23015,35496:23017,35497:23018,35498:23019,35499:23021,35500:23022,35501:23023,35502:23024,35503:23025,35504:23026,35505:23027,35506:23028,35507:23029,35508:23030,35509:23031,35510:23032,35511:23034,35512:23036,35513:23037,35514:23038,35515:23040,35516:23042,35517:23050,35518:23051,35519:23053,35520:23054,35521:23055,35522:23056,35523:23058,35524:23060,35525:23061,35526:23062,35527:23063,35528:23065,35529:23066,35530:23067,35531:23069,35532:23070,35533:23073,35534:23074,35535:23076,35536:23078,35537:23079,35538:23080,35539:23082,35540:23083,35541:23084,35542:23085,35543:23086,35544:23087,35545:23088,35546:23091,35547:23093,35548:23095,35549:23096,35550:23097,35551:23098,35552:23099,35553:23101,35554:23102,35555:23103,35556:23105,35557:23106,35558:23107,35559:23108,35560:23109,35561:23111,35562:23112,35563:23115,35564:23116,35565:23117,35566:23118,35567:23119,35568:23120,35569:23121,35570:23122,35571:23123,35572:23124,35573:23126,35574:23127,35575:23128,35576:23129,35577:23131,35578:23132,35579:23133,35580:23134,35581:23135,35582:23136,35648:23137,35649:23139,35650:23140,35651:23141,35652:23142,35653:23144,35654:23145,35655:23147,35656:23148,35657:23149,35658:23150,35659:23151,35660:23152,35661:23153,35662:23154,35663:23155,35664:23160,35665:23161,35666:23163,35667:23164,35668:23165,35669:23166,35670:23168,35671:23169,35672:23170,35673:23171,35674:23172,35675:23173,35676:23174,35677:23175,35678:23176,35679:23177,35680:23178,35681:23179,35682:23180,35683:23181,35684:23182,35685:23183,35686:23184,35687:23185,35688:23187,35689:23188,35690:23189,35691:23190,35692:23191,35693:23192,35694:23193,35695:23196,35696:23197,35697:23198,35698:23199,35699:23200,35700:23201,35701:23202,35702:23203,35703:23204,35704:23205,35705:23206,35706:23207,35707:23208,35708:23209,35709:23211,35710:23212,35712:23213,35713:23214,35714:23215,35715:23216,35716:23217,35717:23220,35718:23222,35719:23223,35720:23225,35721:23226,35722:23227,35723:23228,35724:23229,35725:23231,35726:23232,35727:23235,35728:23236,35729:23237,35730:23238,35731:23239,35732:23240,35733:23242,35734:23243,35735:23245,35736:23246,35737:23247,35738:23248,35739:23249,35740:23251,35741:23253,35742:23255,35743:23257,35744:23258,35745:23259,35746:23261,35747:23262,35748:23263,35749:23266,35750:23268,35751:23269,35752:23271,35753:23272,35754:23274,35755:23276,35756:23277,35757:23278,35758:23279,35759:23280,35760:23282,35761:23283,35762:23284,35763:23285,35764:23286,35765:23287,35766:23288,35767:23289,35768:23290,35769:23291,35770:23292,35771:23293,35772:23294,35773:23295,35774:23296,35775:23297,35776:23298,35777:23299,35778:23300,35779:23301,35780:23302,35781:23303,35782:23304,35783:23306,35784:23307,35785:23308,35786:23309,35787:23310,35788:23311,35789:23312,35790:23313,35791:23314,35792:23315,35793:23316,35794:23317,35795:23320,35796:23321,35797:23322,35798:23323,35799:23324,35800:23325,35801:23326,35802:23327,35803:23328,35804:23329,35805:23330,35806:23331,35807:23332,35808:23333,35809:23334,35810:23335,35811:23336,35812:23337,35813:23338,35814:23339,35815:23340,35816:23341,35817:23342,35818:23343,35819:23344,35820:23345,35821:23347,35822:23349,35823:23350,35824:23352,35825:23353,35826:23354,35827:23355,35828:23356,35829:23357,35830:23358,35831:23359,35832:23361,35833:23362,35834:23363,35835:23364,35836:23365,35837:23366,35838:23367,35904:23368,35905:23369,35906:23370,35907:23371,35908:23372,35909:23373,35910:23374,35911:23375,35912:23378,35913:23382,35914:23390,35915:23392,35916:23393,35917:23399,35918:23400,35919:23403,35920:23405,35921:23406,35922:23407,35923:23410,35924:23412,35925:23414,35926:23415,35927:23416,35928:23417,35929:23419,35930:23420,35931:23422,35932:23423,35933:23426,35934:23430,35935:23434,35936:23437,35937:23438,35938:23440,35939:23441,35940:23442,35941:23444,35942:23446,35943:23455,35944:23463,35945:23464,35946:23465,35947:23468,35948:23469,35949:23470,35950:23471,35951:23473,35952:23474,35953:23479,35954:23482,35955:23483,35956:23484,35957:23488,35958:23489,35959:23491,35960:23496,35961:23497,35962:23498,35963:23499,35964:23501,35965:23502,35966:23503,35968:23505,35969:23508,35970:23509,35971:23510,35972:23511,35973:23512,35974:23513,35975:23514,35976:23515,35977:23516,35978:23520,35979:23522,35980:23523,35981:23526,35982:23527,35983:23529,35984:23530,35985:23531,35986:23532,35987:23533,35988:23535,35989:23537,35990:23538,35991:23539,35992:23540,35993:23541,35994:23542,35995:23543,35996:23549,35997:23550,35998:23552,35999:23554,36000:23555,36001:23557,36002:23559,36003:23560,36004:23563,36005:23564,36006:23565,36007:23566,36008:23568,36009:23570,36010:23571,36011:23575,36012:23577,36013:23579,36014:23582,36015:23583,36016:23584,36017:23585,36018:23587,36019:23590,36020:23592,36021:23593,36022:23594,36023:23595,36024:23597,36025:23598,36026:23599,36027:23600,36028:23602,36029:23603,36030:23605,36031:23606,36032:23607,36033:23619,36034:23620,36035:23622,36036:23623,36037:23628,36038:23629,36039:23634,36040:23635,36041:23636,36042:23638,36043:23639,36044:23640,36045:23642,36046:23643,36047:23644,36048:23645,36049:23647,36050:23650,36051:23652,36052:23655,36053:23656,36054:23657,36055:23658,36056:23659,36057:23660,36058:23661,36059:23664,36060:23666,36061:23667,36062:23668,36063:23669,36064:23670,36065:23671,36066:23672,36067:23675,36068:23676,36069:23677,36070:23678,36071:23680,36072:23683,36073:23684,36074:23685,36075:23686,36076:23687,36077:23689,36078:23690,36079:23691,36080:23694,36081:23695,36082:23698,36083:23699,36084:23701,36085:23709,36086:23710,36087:23711,36088:23712,36089:23713,36090:23716,36091:23717,36092:23718,36093:23719,36094:23720,36160:23722,36161:23726,36162:23727,36163:23728,36164:23730,36165:23732,36166:23734,36167:23737,36168:23738,36169:23739,36170:23740,36171:23742,36172:23744,36173:23746,36174:23747,36175:23749,36176:23750,36177:23751,36178:23752,36179:23753,36180:23754,36181:23756,36182:23757,36183:23758,36184:23759,36185:23760,36186:23761,36187:23763,36188:23764,36189:23765,36190:23766,36191:23767,36192:23768,36193:23770,36194:23771,36195:23772,36196:23773,36197:23774,36198:23775,36199:23776,36200:23778,36201:23779,36202:23783,36203:23785,36204:23787,36205:23788,36206:23790,36207:23791,36208:23793,36209:23794,36210:23795,36211:23796,36212:23797,36213:23798,36214:23799,36215:23800,36216:23801,36217:23802,36218:23804,36219:23805,36220:23806,36221:23807,36222:23808,36224:23809,36225:23812,36226:23813,36227:23816,36228:23817,36229:23818,36230:23819,36231:23820,36232:23821,36233:23823,36234:23824,36235:23825,36236:23826,36237:23827,36238:23829,36239:23831,36240:23832,36241:23833,36242:23834,36243:23836,36244:23837,36245:23839,36246:23840,36247:23841,36248:23842,36249:23843,36250:23845,36251:23848,36252:23850,36253:23851,36254:23852,36255:23855,36256:23856,36257:23857,36258:23858,36259:23859,36260:23861,36261:23862,36262:23863,36263:23864,36264:23865,36265:23866,36266:23867,36267:23868,36268:23871,36269:23872,36270:23873,36271:23874,36272:23875,36273:23876,36274:23877,36275:23878,36276:23880,36277:23881,36278:23885,36279:23886,36280:23887,36281:23888,36282:23889,36283:23890,36284:23891,36285:23892,36286:23893,36287:23894,36288:23895,36289:23897,36290:23898,36291:23900,36292:23902,36293:23903,36294:23904,36295:23905,36296:23906,36297:23907,36298:23908,36299:23909,36300:23910,36301:23911,36302:23912,36303:23914,36304:23917,36305:23918,36306:23920,36307:23921,36308:23922,36309:23923,36310:23925,36311:23926,36312:23927,36313:23928,36314:23929,36315:23930,36316:23931,36317:23932,36318:23933,36319:23934,36320:23935,36321:23936,36322:23937,36323:23939,36324:23940,36325:23941,36326:23942,36327:23943,36328:23944,36329:23945,36330:23946,36331:23947,36332:23948,36333:23949,36334:23950,36335:23951,36336:23952,36337:23953,36338:23954,36339:23955,36340:23956,36341:23957,36342:23958,36343:23959,36344:23960,36345:23962,36346:23963,36347:23964,36348:23966,36349:23967,36350:23968,36416:23969,36417:23970,36418:23971,36419:23972,36420:23973,36421:23974,36422:23975,36423:23976,36424:23977,36425:23978,36426:23979,36427:23980,36428:23981,36429:23982,36430:23983,36431:23984,36432:23985,36433:23986,36434:23987,36435:23988,36436:23989,36437:23990,36438:23992,36439:23993,36440:23994,36441:23995,36442:23996,36443:23997,36444:23998,36445:23999,36446:24000,36447:24001,36448:24002,36449:24003,36450:24004,36451:24006,36452:24007,36453:24008,36454:24009,36455:24010,36456:24011,36457:24012,36458:24014,36459:24015,36460:24016,36461:24017,36462:24018,36463:24019,36464:24020,36465:24021,36466:24022,36467:24023,36468:24024,36469:24025,36470:24026,36471:24028,36472:24031,36473:24032,36474:24035,36475:24036,36476:24042,36477:24044,36478:24045,36480:24048,36481:24053,36482:24054,36483:24056,36484:24057,36485:24058,36486:24059,36487:24060,36488:24063,36489:24064,36490:24068,36491:24071,36492:24073,36493:24074,36494:24075,36495:24077,36496:24078,36497:24082,36498:24083,36499:24087,36500:24094,36501:24095,36502:24096,36503:24097,36504:24098,36505:24099,36506:24100,36507:24101,36508:24104,36509:24105,36510:24106,36511:24107,36512:24108,36513:24111,36514:24112,36515:24114,36516:24115,36517:24116,36518:24117,36519:24118,36520:24121,36521:24122,36522:24126,36523:24127,36524:24128,36525:24129,36526:24131,36527:24134,36528:24135,36529:24136,36530:24137,36531:24138,36532:24139,36533:24141,36534:24142,36535:24143,36536:24144,36537:24145,36538:24146,36539:24147,36540:24150,36541:24151,36542:24152,36543:24153,36544:24154,36545:24156,36546:24157,36547:24159,36548:24160,36549:24163,36550:24164,36551:24165,36552:24166,36553:24167,36554:24168,36555:24169,36556:24170,36557:24171,36558:24172,36559:24173,36560:24174,36561:24175,36562:24176,36563:24177,36564:24181,36565:24183,36566:24185,36567:24190,36568:24193,36569:24194,36570:24195,36571:24197,36572:24200,36573:24201,36574:24204,36575:24205,36576:24206,36577:24210,36578:24216,36579:24219,36580:24221,36581:24225,36582:24226,36583:24227,36584:24228,36585:24232,36586:24233,36587:24234,36588:24235,36589:24236,36590:24238,36591:24239,36592:24240,36593:24241,36594:24242,36595:24244,36596:24250,36597:24251,36598:24252,36599:24253,36600:24255,36601:24256,36602:24257,36603:24258,36604:24259,36605:24260,36606:24261,36672:24262,36673:24263,36674:24264,36675:24267,36676:24268,36677:24269,36678:24270,36679:24271,36680:24272,36681:24276,36682:24277,36683:24279,36684:24280,36685:24281,36686:24282,36687:24284,36688:24285,36689:24286,36690:24287,36691:24288,36692:24289,36693:24290,36694:24291,36695:24292,36696:24293,36697:24294,36698:24295,36699:24297,36700:24299,36701:24300,36702:24301,36703:24302,36704:24303,36705:24304,36706:24305,36707:24306,36708:24307,36709:24309,36710:24312,36711:24313,36712:24315,36713:24316,36714:24317,36715:24325,36716:24326,36717:24327,36718:24329,36719:24332,36720:24333,36721:24334,36722:24336,36723:24338,36724:24340,36725:24342,36726:24345,36727:24346,36728:24348,36729:24349,36730:24350,36731:24353,36732:24354,36733:24355,36734:24356,36736:24360,36737:24363,36738:24364,36739:24366,36740:24368,36741:24370,36742:24371,36743:24372,36744:24373,36745:24374,36746:24375,36747:24376,36748:24379,36749:24381,36750:24382,36751:24383,36752:24385,36753:24386,36754:24387,36755:24388,36756:24389,36757:24390,36758:24391,36759:24392,36760:24393,36761:24394,36762:24395,36763:24396,36764:24397,36765:24398,36766:24399,36767:24401,36768:24404,36769:24409,36770:24410,36771:24411,36772:24412,36773:24414,36774:24415,36775:24416,36776:24419,36777:24421,36778:24423,36779:24424,36780:24427,36781:24430,36782:24431,36783:24434,36784:24436,36785:24437,36786:24438,36787:24440,36788:24442,36789:24445,36790:24446,36791:24447,36792:24451,36793:24454,36794:24461,36795:24462,36796:24463,36797:24465,36798:24467,36799:24468,36800:24470,36801:24474,36802:24475,36803:24477,36804:24478,36805:24479,36806:24480,36807:24482,36808:24483,36809:24484,36810:24485,36811:24486,36812:24487,36813:24489,36814:24491,36815:24492,36816:24495,36817:24496,36818:24497,36819:24498,36820:24499,36821:24500,36822:24502,36823:24504,36824:24505,36825:24506,36826:24507,36827:24510,36828:24511,36829:24512,36830:24513,36831:24514,36832:24519,36833:24520,36834:24522,36835:24523,36836:24526,36837:24531,36838:24532,36839:24533,36840:24538,36841:24539,36842:24540,36843:24542,36844:24543,36845:24546,36846:24547,36847:24549,36848:24550,36849:24552,36850:24553,36851:24556,36852:24559,36853:24560,36854:24562,36855:24563,36856:24564,36857:24566,36858:24567,36859:24569,36860:24570,36861:24572,36862:24583,36928:24584,36929:24585,36930:24587,36931:24588,36932:24592,36933:24593,36934:24595,36935:24599,36936:24600,36937:24602,36938:24606,36939:24607,36940:24610,36941:24611,36942:24612,36943:24620,36944:24621,36945:24622,36946:24624,36947:24625,36948:24626,36949:24627,36950:24628,36951:24630,36952:24631,36953:24632,36954:24633,36955:24634,36956:24637,36957:24638,36958:24640,36959:24644,36960:24645,36961:24646,36962:24647,36963:24648,36964:24649,36965:24650,36966:24652,36967:24654,36968:24655,36969:24657,36970:24659,36971:24660,36972:24662,36973:24663,36974:24664,36975:24667,36976:24668,36977:24670,36978:24671,36979:24672,36980:24673,36981:24677,36982:24678,36983:24686,36984:24689,36985:24690,36986:24692,36987:24693,36988:24695,36989:24702,36990:24704,36992:24705,36993:24706,36994:24709,36995:24710,36996:24711,36997:24712,36998:24714,36999:24715,37000:24718,37001:24719,37002:24720,37003:24721,37004:24723,37005:24725,37006:24727,37007:24728,37008:24729,37009:24732,37010:24734,37011:24737,37012:24738,37013:24740,37014:24741,37015:24743,37016:24745,37017:24746,37018:24750,37019:24752,37020:24755,37021:24757,37022:24758,37023:24759,37024:24761,37025:24762,37026:24765,37027:24766,37028:24767,37029:24768,37030:24769,37031:24770,37032:24771,37033:24772,37034:24775,37035:24776,37036:24777,37037:24780,37038:24781,37039:24782,37040:24783,37041:24784,37042:24786,37043:24787,37044:24788,37045:24790,37046:24791,37047:24793,37048:24795,37049:24798,37050:24801,37051:24802,37052:24803,37053:24804,37054:24805,37055:24810,37056:24817,37057:24818,37058:24821,37059:24823,37060:24824,37061:24827,37062:24828,37063:24829,37064:24830,37065:24831,37066:24834,37067:24835,37068:24836,37069:24837,37070:24839,37071:24842,37072:24843,37073:24844,37074:24848,37075:24849,37076:24850,37077:24851,37078:24852,37079:24854,37080:24855,37081:24856,37082:24857,37083:24859,37084:24860,37085:24861,37086:24862,37087:24865,37088:24866,37089:24869,37090:24872,37091:24873,37092:24874,37093:24876,37094:24877,37095:24878,37096:24879,37097:24880,37098:24881,37099:24882,37100:24883,37101:24884,37102:24885,37103:24886,37104:24887,37105:24888,37106:24889,37107:24890,37108:24891,37109:24892,37110:24893,37111:24894,37112:24896,37113:24897,37114:24898,37115:24899,37116:24900,37117:24901,37118:24902,37184:24903,37185:24905,37186:24907,37187:24909,37188:24911,37189:24912,37190:24914,37191:24915,37192:24916,37193:24918,37194:24919,37195:24920,37196:24921,37197:24922,37198:24923,37199:24924,37200:24926,37201:24927,37202:24928,37203:24929,37204:24931,37205:24932,37206:24933,37207:24934,37208:24937,37209:24938,37210:24939,37211:24940,37212:24941,37213:24942,37214:24943,37215:24945,37216:24946,37217:24947,37218:24948,37219:24950,37220:24952,37221:24953,37222:24954,37223:24955,37224:24956,37225:24957,37226:24958,37227:24959,37228:24960,37229:24961,37230:24962,37231:24963,37232:24964,37233:24965,37234:24966,37235:24967,37236:24968,37237:24969,37238:24970,37239:24972,37240:24973,37241:24975,37242:24976,37243:24977,37244:24978,37245:24979,37246:24981,37248:24982,37249:24983,37250:24984,37251:24985,37252:24986,37253:24987,37254:24988,37255:24990,37256:24991,37257:24992,37258:24993,37259:24994,37260:24995,37261:24996,37262:24997,37263:24998,37264:25002,37265:25003,37266:25005,37267:25006,37268:25007,37269:25008,37270:25009,37271:25010,37272:25011,37273:25012,37274:25013,37275:25014,37276:25016,37277:25017,37278:25018,37279:25019,37280:25020,37281:25021,37282:25023,37283:25024,37284:25025,37285:25027,37286:25028,37287:25029,37288:25030,37289:25031,37290:25033,37291:25036,37292:25037,37293:25038,37294:25039,37295:25040,37296:25043,37297:25045,37298:25046,37299:25047,37300:25048,37301:25049,37302:25050,37303:25051,37304:25052,37305:25053,37306:25054,37307:25055,37308:25056,37309:25057,37310:25058,37311:25059,37312:25060,37313:25061,37314:25063,37315:25064,37316:25065,37317:25066,37318:25067,37319:25068,37320:25069,37321:25070,37322:25071,37323:25072,37324:25073,37325:25074,37326:25075,37327:25076,37328:25078,37329:25079,37330:25080,37331:25081,37332:25082,37333:25083,37334:25084,37335:25085,37336:25086,37337:25088,37338:25089,37339:25090,37340:25091,37341:25092,37342:25093,37343:25095,37344:25097,37345:25107,37346:25108,37347:25113,37348:25116,37349:25117,37350:25118,37351:25120,37352:25123,37353:25126,37354:25127,37355:25128,37356:25129,37357:25131,37358:25133,37359:25135,37360:25136,37361:25137,37362:25138,37363:25141,37364:25142,37365:25144,37366:25145,37367:25146,37368:25147,37369:25148,37370:25154,37371:25156,37372:25157,37373:25158,37374:25162,37440:25167,37441:25168,37442:25173,37443:25174,37444:25175,37445:25177,37446:25178,37447:25180,37448:25181,37449:25182,37450:25183,37451:25184,37452:25185,37453:25186,37454:25188,37455:25189,37456:25192,37457:25201,37458:25202,37459:25204,37460:25205,37461:25207,37462:25208,37463:25210,37464:25211,37465:25213,37466:25217,37467:25218,37468:25219,37469:25221,37470:25222,37471:25223,37472:25224,37473:25227,37474:25228,37475:25229,37476:25230,37477:25231,37478:25232,37479:25236,37480:25241,37481:25244,37482:25245,37483:25246,37484:25251,37485:25254,37486:25255,37487:25257,37488:25258,37489:25261,37490:25262,37491:25263,37492:25264,37493:25266,37494:25267,37495:25268,37496:25270,37497:25271,37498:25272,37499:25274,37500:25278,37501:25280,37502:25281,37504:25283,37505:25291,37506:25295,37507:25297,37508:25301,37509:25309,37510:25310,37511:25312,37512:25313,37513:25316,37514:25322,37515:25323,37516:25328,37517:25330,37518:25333,37519:25336,37520:25337,37521:25338,37522:25339,37523:25344,37524:25347,37525:25348,37526:25349,37527:25350,37528:25354,37529:25355,37530:25356,37531:25357,37532:25359,37533:25360,37534:25362,37535:25363,37536:25364,37537:25365,37538:25367,37539:25368,37540:25369,37541:25372,37542:25382,37543:25383,37544:25385,37545:25388,37546:25389,37547:25390,37548:25392,37549:25393,37550:25395,37551:25396,37552:25397,37553:25398,37554:25399,37555:25400,37556:25403,37557:25404,37558:25406,37559:25407,37560:25408,37561:25409,37562:25412,37563:25415,37564:25416,37565:25418,37566:25425,37567:25426,37568:25427,37569:25428,37570:25430,37571:25431,37572:25432,37573:25433,37574:25434,37575:25435,37576:25436,37577:25437,37578:25440,37579:25444,37580:25445,37581:25446,37582:25448,37583:25450,37584:25451,37585:25452,37586:25455,37587:25456,37588:25458,37589:25459,37590:25460,37591:25461,37592:25464,37593:25465,37594:25468,37595:25469,37596:25470,37597:25471,37598:25473,37599:25475,37600:25476,37601:25477,37602:25478,37603:25483,37604:25485,37605:25489,37606:25491,37607:25492,37608:25493,37609:25495,37610:25497,37611:25498,37612:25499,37613:25500,37614:25501,37615:25502,37616:25503,37617:25505,37618:25508,37619:25510,37620:25515,37621:25519,37622:25521,37623:25522,37624:25525,37625:25526,37626:25529,37627:25531,37628:25533,37629:25535,37630:25536,37696:25537,37697:25538,37698:25539,37699:25541,37700:25543,37701:25544,37702:25546,37703:25547,37704:25548,37705:25553,37706:25555,37707:25556,37708:25557,37709:25559,37710:25560,37711:25561,37712:25562,37713:25563,37714:25564,37715:25565,37716:25567,37717:25570,37718:25572,37719:25573,37720:25574,37721:25575,37722:25576,37723:25579,37724:25580,37725:25582,37726:25583,37727:25584,37728:25585,37729:25587,37730:25589,37731:25591,37732:25593,37733:25594,37734:25595,37735:25596,37736:25598,37737:25603,37738:25604,37739:25606,37740:25607,37741:25608,37742:25609,37743:25610,37744:25613,37745:25614,37746:25617,37747:25618,37748:25621,37749:25622,37750:25623,37751:25624,37752:25625,37753:25626,37754:25629,37755:25631,37756:25634,37757:25635,37758:25636,37760:25637,37761:25639,37762:25640,37763:25641,37764:25643,37765:25646,37766:25647,37767:25648,37768:25649,37769:25650,37770:25651,37771:25653,37772:25654,37773:25655,37774:25656,37775:25657,37776:25659,37777:25660,37778:25662,37779:25664,37780:25666,37781:25667,37782:25673,37783:25675,37784:25676,37785:25677,37786:25678,37787:25679,37788:25680,37789:25681,37790:25683,37791:25685,37792:25686,37793:25687,37794:25689,37795:25690,37796:25691,37797:25692,37798:25693,37799:25695,37800:25696,37801:25697,37802:25698,37803:25699,37804:25700,37805:25701,37806:25702,37807:25704,37808:25706,37809:25707,37810:25708,37811:25710,37812:25711,37813:25712,37814:25713,37815:25714,37816:25715,37817:25716,37818:25717,37819:25718,37820:25719,37821:25723,37822:25724,37823:25725,37824:25726,37825:25727,37826:25728,37827:25729,37828:25731,37829:25734,37830:25736,37831:25737,37832:25738,37833:25739,37834:25740,37835:25741,37836:25742,37837:25743,37838:25744,37839:25747,37840:25748,37841:25751,37842:25752,37843:25754,37844:25755,37845:25756,37846:25757,37847:25759,37848:25760,37849:25761,37850:25762,37851:25763,37852:25765,37853:25766,37854:25767,37855:25768,37856:25770,37857:25771,37858:25775,37859:25777,37860:25778,37861:25779,37862:25780,37863:25782,37864:25785,37865:25787,37866:25789,37867:25790,37868:25791,37869:25793,37870:25795,37871:25796,37872:25798,37873:25799,37874:25800,37875:25801,37876:25802,37877:25803,37878:25804,37879:25807,37880:25809,37881:25811,37882:25812,37883:25813,37884:25814,37885:25817,37886:25818,37952:25819,37953:25820,37954:25821,37955:25823,37956:25824,37957:25825,37958:25827,37959:25829,37960:25831,37961:25832,37962:25833,37963:25834,37964:25835,37965:25836,37966:25837,37967:25838,37968:25839,37969:25840,37970:25841,37971:25842,37972:25843,37973:25844,37974:25845,37975:25846,37976:25847,37977:25848,37978:25849,37979:25850,37980:25851,37981:25852,37982:25853,37983:25854,37984:25855,37985:25857,37986:25858,37987:25859,37988:25860,37989:25861,37990:25862,37991:25863,37992:25864,37993:25866,37994:25867,37995:25868,37996:25869,37997:25870,37998:25871,37999:25872,38000:25873,38001:25875,38002:25876,38003:25877,38004:25878,38005:25879,38006:25881,38007:25882,38008:25883,38009:25884,38010:25885,38011:25886,38012:25887,38013:25888,38014:25889,38016:25890,38017:25891,38018:25892,38019:25894,38020:25895,38021:25896,38022:25897,38023:25898,38024:25900,38025:25901,38026:25904,38027:25905,38028:25906,38029:25907,38030:25911,38031:25914,38032:25916,38033:25917,38034:25920,38035:25921,38036:25922,38037:25923,38038:25924,38039:25926,38040:25927,38041:25930,38042:25931,38043:25933,38044:25934,38045:25936,38046:25938,38047:25939,38048:25940,38049:25943,38050:25944,38051:25946,38052:25948,38053:25951,38054:25952,38055:25953,38056:25956,38057:25957,38058:25959,38059:25960,38060:25961,38061:25962,38062:25965,38063:25966,38064:25967,38065:25969,38066:25971,38067:25973,38068:25974,38069:25976,38070:25977,38071:25978,38072:25979,38073:25980,38074:25981,38075:25982,38076:25983,38077:25984,38078:25985,38079:25986,38080:25987,38081:25988,38082:25989,38083:25990,38084:25992,38085:25993,38086:25994,38087:25997,38088:25998,38089:25999,38090:26002,38091:26004,38092:26005,38093:26006,38094:26008,38095:26010,38096:26013,38097:26014,38098:26016,38099:26018,38100:26019,38101:26022,38102:26024,38103:26026,38104:26028,38105:26030,38106:26033,38107:26034,38108:26035,38109:26036,38110:26037,38111:26038,38112:26039,38113:26040,38114:26042,38115:26043,38116:26046,38117:26047,38118:26048,38119:26050,38120:26055,38121:26056,38122:26057,38123:26058,38124:26061,38125:26064,38126:26065,38127:26067,38128:26068,38129:26069,38130:26072,38131:26073,38132:26074,38133:26075,38134:26076,38135:26077,38136:26078,38137:26079,38138:26081,38139:26083,38140:26084,38141:26090,38142:26091,38208:26098,38209:26099,38210:26100,38211:26101,38212:26104,38213:26105,38214:26107,38215:26108,38216:26109,38217:26110,38218:26111,38219:26113,38220:26116,38221:26117,38222:26119,38223:26120,38224:26121,38225:26123,38226:26125,38227:26128,38228:26129,38229:26130,38230:26134,38231:26135,38232:26136,38233:26138,38234:26139,38235:26140,38236:26142,38237:26145,38238:26146,38239:26147,38240:26148,38241:26150,38242:26153,38243:26154,38244:26155,38245:26156,38246:26158,38247:26160,38248:26162,38249:26163,38250:26167,38251:26168,38252:26169,38253:26170,38254:26171,38255:26173,38256:26175,38257:26176,38258:26178,38259:26180,38260:26181,38261:26182,38262:26183,38263:26184,38264:26185,38265:26186,38266:26189,38267:26190,38268:26192,38269:26193,38270:26200,38272:26201,38273:26203,38274:26204,38275:26205,38276:26206,38277:26208,38278:26210,38279:26211,38280:26213,38281:26215,38282:26217,38283:26218,38284:26219,38285:26220,38286:26221,38287:26225,38288:26226,38289:26227,38290:26229,38291:26232,38292:26233,38293:26235,38294:26236,38295:26237,38296:26239,38297:26240,38298:26241,38299:26243,38300:26245,38301:26246,38302:26248,38303:26249,38304:26250,38305:26251,38306:26253,38307:26254,38308:26255,38309:26256,38310:26258,38311:26259,38312:26260,38313:26261,38314:26264,38315:26265,38316:26266,38317:26267,38318:26268,38319:26270,38320:26271,38321:26272,38322:26273,38323:26274,38324:26275,38325:26276,38326:26277,38327:26278,38328:26281,38329:26282,38330:26283,38331:26284,38332:26285,38333:26287,38334:26288,38335:26289,38336:26290,38337:26291,38338:26293,38339:26294,38340:26295,38341:26296,38342:26298,38343:26299,38344:26300,38345:26301,38346:26303,38347:26304,38348:26305,38349:26306,38350:26307,38351:26308,38352:26309,38353:26310,38354:26311,38355:26312,38356:26313,38357:26314,38358:26315,38359:26316,38360:26317,38361:26318,38362:26319,38363:26320,38364:26321,38365:26322,38366:26323,38367:26324,38368:26325,38369:26326,38370:26327,38371:26328,38372:26330,38373:26334,38374:26335,38375:26336,38376:26337,38377:26338,38378:26339,38379:26340,38380:26341,38381:26343,38382:26344,38383:26346,38384:26347,38385:26348,38386:26349,38387:26350,38388:26351,38389:26353,38390:26357,38391:26358,38392:26360,38393:26362,38394:26363,38395:26365,38396:26369,38397:26370,38398:26371,38464:26372,38465:26373,38466:26374,38467:26375,38468:26380,38469:26382,38470:26383,38471:26385,38472:26386,38473:26387,38474:26390,38475:26392,38476:26393,38477:26394,38478:26396,38479:26398,38480:26400,38481:26401,38482:26402,38483:26403,38484:26404,38485:26405,38486:26407,38487:26409,38488:26414,38489:26416,38490:26418,38491:26419,38492:26422,38493:26423,38494:26424,38495:26425,38496:26427,38497:26428,38498:26430,38499:26431,38500:26433,38501:26436,38502:26437,38503:26439,38504:26442,38505:26443,38506:26445,38507:26450,38508:26452,38509:26453,38510:26455,38511:26456,38512:26457,38513:26458,38514:26459,38515:26461,38516:26466,38517:26467,38518:26468,38519:26470,38520:26471,38521:26475,38522:26476,38523:26478,38524:26481,38525:26484,38526:26486,38528:26488,38529:26489,38530:26490,38531:26491,38532:26493,38533:26496,38534:26498,38535:26499,38536:26501,38537:26502,38538:26504,38539:26506,38540:26508,38541:26509,38542:26510,38543:26511,38544:26513,38545:26514,38546:26515,38547:26516,38548:26518,38549:26521,38550:26523,38551:26527,38552:26528,38553:26529,38554:26532,38555:26534,38556:26537,38557:26540,38558:26542,38559:26545,38560:26546,38561:26548,38562:26553,38563:26554,38564:26555,38565:26556,38566:26557,38567:26558,38568:26559,38569:26560,38570:26562,38571:26565,38572:26566,38573:26567,38574:26568,38575:26569,38576:26570,38577:26571,38578:26572,38579:26573,38580:26574,38581:26581,38582:26582,38583:26583,38584:26587,38585:26591,38586:26593,38587:26595,38588:26596,38589:26598,38590:26599,38591:26600,38592:26602,38593:26603,38594:26605,38595:26606,38596:26610,38597:26613,38598:26614,38599:26615,38600:26616,38601:26617,38602:26618,38603:26619,38604:26620,38605:26622,38606:26625,38607:26626,38608:26627,38609:26628,38610:26630,38611:26637,38612:26640,38613:26642,38614:26644,38615:26645,38616:26648,38617:26649,38618:26650,38619:26651,38620:26652,38621:26654,38622:26655,38623:26656,38624:26658,38625:26659,38626:26660,38627:26661,38628:26662,38629:26663,38630:26664,38631:26667,38632:26668,38633:26669,38634:26670,38635:26671,38636:26672,38637:26673,38638:26676,38639:26677,38640:26678,38641:26682,38642:26683,38643:26687,38644:26695,38645:26699,38646:26701,38647:26703,38648:26706,38649:26710,38650:26711,38651:26712,38652:26713,38653:26714,38654:26715,38720:26716,38721:26717,38722:26718,38723:26719,38724:26730,38725:26732,38726:26733,38727:26734,38728:26735,38729:26736,38730:26737,38731:26738,38732:26739,38733:26741,38734:26744,38735:26745,38736:26746,38737:26747,38738:26748,38739:26749,38740:26750,38741:26751,38742:26752,38743:26754,38744:26756,38745:26759,38746:26760,38747:26761,38748:26762,38749:26763,38750:26764,38751:26765,38752:26766,38753:26768,38754:26769,38755:26770,38756:26772,38757:26773,38758:26774,38759:26776,38760:26777,38761:26778,38762:26779,38763:26780,38764:26781,38765:26782,38766:26783,38767:26784,38768:26785,38769:26787,38770:26788,38771:26789,38772:26793,38773:26794,38774:26795,38775:26796,38776:26798,38777:26801,38778:26802,38779:26804,38780:26806,38781:26807,38782:26808,38784:26809,38785:26810,38786:26811,38787:26812,38788:26813,38789:26814,38790:26815,38791:26817,38792:26819,38793:26820,38794:26821,38795:26822,38796:26823,38797:26824,38798:26826,38799:26828,38800:26830,38801:26831,38802:26832,38803:26833,38804:26835,38805:26836,38806:26838,38807:26839,38808:26841,38809:26843,38810:26844,38811:26845,38812:26846,38813:26847,38814:26849,38815:26850,38816:26852,38817:26853,38818:26854,38819:26855,38820:26856,38821:26857,38822:26858,38823:26859,38824:26860,38825:26861,38826:26863,38827:26866,38828:26867,38829:26868,38830:26870,38831:26871,38832:26872,38833:26875,38834:26877,38835:26878,38836:26879,38837:26880,38838:26882,38839:26883,38840:26884,38841:26886,38842:26887,38843:26888,38844:26889,38845:26890,38846:26892,38847:26895,38848:26897,38849:26899,38850:26900,38851:26901,38852:26902,38853:26903,38854:26904,38855:26905,38856:26906,38857:26907,38858:26908,38859:26909,38860:26910,38861:26913,38862:26914,38863:26915,38864:26917,38865:26918,38866:26919,38867:26920,38868:26921,38869:26922,38870:26923,38871:26924,38872:26926,38873:26927,38874:26929,38875:26930,38876:26931,38877:26933,38878:26934,38879:26935,38880:26936,38881:26938,38882:26939,38883:26940,38884:26942,38885:26944,38886:26945,38887:26947,38888:26948,38889:26949,38890:26950,38891:26951,38892:26952,38893:26953,38894:26954,38895:26955,38896:26956,38897:26957,38898:26958,38899:26959,38900:26960,38901:26961,38902:26962,38903:26963,38904:26965,38905:26966,38906:26968,38907:26969,38908:26971,38909:26972,38910:26975,38976:26977,38977:26978,38978:26980,38979:26981,38980:26983,38981:26984,38982:26985,38983:26986,38984:26988,38985:26989,38986:26991,38987:26992,38988:26994,38989:26995,38990:26996,38991:26997,38992:26998,38993:27002,38994:27003,38995:27005,38996:27006,38997:27007,38998:27009,38999:27011,39000:27013,39001:27018,39002:27019,39003:27020,39004:27022,39005:27023,39006:27024,39007:27025,39008:27026,39009:27027,39010:27030,39011:27031,39012:27033,39013:27034,39014:27037,39015:27038,39016:27039,39017:27040,39018:27041,39019:27042,39020:27043,39021:27044,39022:27045,39023:27046,39024:27049,39025:27050,39026:27052,39027:27054,39028:27055,39029:27056,39030:27058,39031:27059,39032:27061,39033:27062,39034:27064,39035:27065,39036:27066,39037:27068,39038:27069,39040:27070,39041:27071,39042:27072,39043:27074,39044:27075,39045:27076,39046:27077,39047:27078,39048:27079,39049:27080,39050:27081,39051:27083,39052:27085,39053:27087,39054:27089,39055:27090,39056:27091,39057:27093,39058:27094,39059:27095,39060:27096,39061:27097,39062:27098,39063:27100,39064:27101,39065:27102,39066:27105,39067:27106,39068:27107,39069:27108,39070:27109,39071:27110,39072:27111,39073:27112,39074:27113,39075:27114,39076:27115,39077:27116,39078:27118,39079:27119,39080:27120,39081:27121,39082:27123,39083:27124,39084:27125,39085:27126,39086:27127,39087:27128,39088:27129,39089:27130,39090:27131,39091:27132,39092:27134,39093:27136,39094:27137,39095:27138,39096:27139,39097:27140,39098:27141,39099:27142,39100:27143,39101:27144,39102:27145,39103:27147,39104:27148,39105:27149,39106:27150,39107:27151,39108:27152,39109:27153,39110:27154,39111:27155,39112:27156,39113:27157,39114:27158,39115:27161,39116:27162,39117:27163,39118:27164,39119:27165,39120:27166,39121:27168,39122:27170,39123:27171,39124:27172,39125:27173,39126:27174,39127:27175,39128:27177,39129:27179,39130:27180,39131:27181,39132:27182,39133:27184,39134:27186,39135:27187,39136:27188,39137:27190,39138:27191,39139:27192,39140:27193,39141:27194,39142:27195,39143:27196,39144:27199,39145:27200,39146:27201,39147:27202,39148:27203,39149:27205,39150:27206,39151:27208,39152:27209,39153:27210,39154:27211,39155:27212,39156:27213,39157:27214,39158:27215,39159:27217,39160:27218,39161:27219,39162:27220,39163:27221,39164:27222,39165:27223,39166:27226,39232:27228,39233:27229,39234:27230,39235:27231,39236:27232,39237:27234,39238:27235,39239:27236,39240:27238,39241:27239,39242:27240,39243:27241,39244:27242,39245:27243,39246:27244,39247:27245,39248:27246,39249:27247,39250:27248,39251:27250,39252:27251,39253:27252,39254:27253,39255:27254,39256:27255,39257:27256,39258:27258,39259:27259,39260:27261,39261:27262,39262:27263,39263:27265,39264:27266,39265:27267,39266:27269,39267:27270,39268:27271,39269:27272,39270:27273,39271:27274,39272:27275,39273:27276,39274:27277,39275:27279,39276:27282,39277:27283,39278:27284,39279:27285,39280:27286,39281:27288,39282:27289,39283:27290,39284:27291,39285:27292,39286:27293,39287:27294,39288:27295,39289:27297,39290:27298,39291:27299,39292:27300,39293:27301,39294:27302,39296:27303,39297:27304,39298:27306,39299:27309,39300:27310,39301:27311,39302:27312,39303:27313,39304:27314,39305:27315,39306:27316,39307:27317,39308:27318,39309:27319,39310:27320,39311:27321,39312:27322,39313:27323,39314:27324,39315:27325,39316:27326,39317:27327,39318:27328,39319:27329,39320:27330,39321:27331,39322:27332,39323:27333,39324:27334,39325:27335,39326:27336,39327:27337,39328:27338,39329:27339,39330:27340,39331:27341,39332:27342,39333:27343,39334:27344,39335:27345,39336:27346,39337:27347,39338:27348,39339:27349,39340:27350,39341:27351,39342:27352,39343:27353,39344:27354,39345:27355,39346:27356,39347:27357,39348:27358,39349:27359,39350:27360,39351:27361,39352:27362,39353:27363,39354:27364,39355:27365,39356:27366,39357:27367,39358:27368,39359:27369,39360:27370,39361:27371,39362:27372,39363:27373,39364:27374,39365:27375,39366:27376,39367:27377,39368:27378,39369:27379,39370:27380,39371:27381,39372:27382,39373:27383,39374:27384,39375:27385,39376:27386,39377:27387,39378:27388,39379:27389,39380:27390,39381:27391,39382:27392,39383:27393,39384:27394,39385:27395,39386:27396,39387:27397,39388:27398,39389:27399,39390:27400,39391:27401,39392:27402,39393:27403,39394:27404,39395:27405,39396:27406,39397:27407,39398:27408,39399:27409,39400:27410,39401:27411,39402:27412,39403:27413,39404:27414,39405:27415,39406:27416,39407:27417,39408:27418,39409:27419,39410:27420,39411:27421,39412:27422,39413:27423,39414:27429,39415:27430,39416:27432,39417:27433,39418:27434,39419:27435,39420:27436,39421:27437,39422:27438,39488:27439,39489:27440,39490:27441,39491:27443,39492:27444,39493:27445,39494:27446,39495:27448,39496:27451,39497:27452,39498:27453,39499:27455,39500:27456,39501:27457,39502:27458,39503:27460,39504:27461,39505:27464,39506:27466,39507:27467,39508:27469,39509:27470,39510:27471,39511:27472,39512:27473,39513:27474,39514:27475,39515:27476,39516:27477,39517:27478,39518:27479,39519:27480,39520:27482,39521:27483,39522:27484,39523:27485,39524:27486,39525:27487,39526:27488,39527:27489,39528:27496,39529:27497,39530:27499,39531:27500,39532:27501,39533:27502,39534:27503,39535:27504,39536:27505,39537:27506,39538:27507,39539:27508,39540:27509,39541:27510,39542:27511,39543:27512,39544:27514,39545:27517,39546:27518,39547:27519,39548:27520,39549:27525,39550:27528,39552:27532,39553:27534,39554:27535,39555:27536,39556:27537,39557:27540,39558:27541,39559:27543,39560:27544,39561:27545,39562:27548,39563:27549,39564:27550,39565:27551,39566:27552,39567:27554,39568:27555,39569:27556,39570:27557,39571:27558,39572:27559,39573:27560,39574:27561,39575:27563,39576:27564,39577:27565,39578:27566,39579:27567,39580:27568,39581:27569,39582:27570,39583:27574,39584:27576,39585:27577,39586:27578,39587:27579,39588:27580,39589:27581,39590:27582,39591:27584,39592:27587,39593:27588,39594:27590,39595:27591,39596:27592,39597:27593,39598:27594,39599:27596,39600:27598,39601:27600,39602:27601,39603:27608,39604:27610,39605:27612,39606:27613,39607:27614,39608:27615,39609:27616,39610:27618,39611:27619,39612:27620,39613:27621,39614:27622,39615:27623,39616:27624,39617:27625,39618:27628,39619:27629,39620:27630,39621:27632,39622:27633,39623:27634,39624:27636,39625:27638,39626:27639,39627:27640,39628:27642,39629:27643,39630:27644,39631:27646,39632:27647,39633:27648,39634:27649,39635:27650,39636:27651,39637:27652,39638:27656,39639:27657,39640:27658,39641:27659,39642:27660,39643:27662,39644:27666,39645:27671,39646:27676,39647:27677,39648:27678,39649:27680,39650:27683,39651:27685,39652:27691,39653:27692,39654:27693,39655:27697,39656:27699,39657:27702,39658:27703,39659:27705,39660:27706,39661:27707,39662:27708,39663:27710,39664:27711,39665:27715,39666:27716,39667:27717,39668:27720,39669:27723,39670:27724,39671:27725,39672:27726,39673:27727,39674:27729,39675:27730,39676:27731,39677:27734,39678:27736,39744:27737,39745:27738,39746:27746,39747:27747,39748:27749,39749:27750,39750:27751,39751:27755,39752:27756,39753:27757,39754:27758,39755:27759,39756:27761,39757:27763,39758:27765,39759:27767,39760:27768,39761:27770,39762:27771,39763:27772,39764:27775,39765:27776,39766:27780,39767:27783,39768:27786,39769:27787,39770:27789,39771:27790,39772:27793,39773:27794,39774:27797,39775:27798,39776:27799,39777:27800,39778:27802,39779:27804,39780:27805,39781:27806,39782:27808,39783:27810,39784:27816,39785:27820,39786:27823,39787:27824,39788:27828,39789:27829,39790:27830,39791:27831,39792:27834,39793:27840,39794:27841,39795:27842,39796:27843,39797:27846,39798:27847,39799:27848,39800:27851,39801:27853,39802:27854,39803:27855,39804:27857,39805:27858,39806:27864,39808:27865,39809:27866,39810:27868,39811:27869,39812:27871,39813:27876,39814:27878,39815:27879,39816:27881,39817:27884,39818:27885,39819:27890,39820:27892,39821:27897,39822:27903,39823:27904,39824:27906,39825:27907,39826:27909,39827:27910,39828:27912,39829:27913,39830:27914,39831:27917,39832:27919,39833:27920,39834:27921,39835:27923,39836:27924,39837:27925,39838:27926,39839:27928,39840:27932,39841:27933,39842:27935,39843:27936,39844:27937,39845:27938,39846:27939,39847:27940,39848:27942,39849:27944,39850:27945,39851:27948,39852:27949,39853:27951,39854:27952,39855:27956,39856:27958,39857:27959,39858:27960,39859:27962,39860:27967,39861:27968,39862:27970,39863:27972,39864:27977,39865:27980,39866:27984,39867:27989,39868:27990,39869:27991,39870:27992,39871:27995,39872:27997,39873:27999,39874:28001,39875:28002,39876:28004,39877:28005,39878:28007,39879:28008,39880:28011,39881:28012,39882:28013,39883:28016,39884:28017,39885:28018,39886:28019,39887:28021,39888:28022,39889:28025,39890:28026,39891:28027,39892:28029,39893:28030,39894:28031,39895:28032,39896:28033,39897:28035,39898:28036,39899:28038,39900:28039,39901:28042,39902:28043,39903:28045,39904:28047,39905:28048,39906:28050,39907:28054,39908:28055,39909:28056,39910:28057,39911:28058,39912:28060,39913:28066,39914:28069,39915:28076,39916:28077,39917:28080,39918:28081,39919:28083,39920:28084,39921:28086,39922:28087,39923:28089,39924:28090,39925:28091,39926:28092,39927:28093,39928:28094,39929:28097,39930:28098,39931:28099,39932:28104,39933:28105,39934:28106,40000:28109,40001:28110,40002:28111,40003:28112,40004:28114,40005:28115,40006:28116,40007:28117,40008:28119,40009:28122,40010:28123,40011:28124,40012:28127,40013:28130,40014:28131,40015:28133,40016:28135,40017:28136,40018:28137,40019:28138,40020:28141,40021:28143,40022:28144,40023:28146,40024:28148,40025:28149,40026:28150,40027:28152,40028:28154,40029:28157,40030:28158,40031:28159,40032:28160,40033:28161,40034:28162,40035:28163,40036:28164,40037:28166,40038:28167,40039:28168,40040:28169,40041:28171,40042:28175,40043:28178,40044:28179,40045:28181,40046:28184,40047:28185,40048:28187,40049:28188,40050:28190,40051:28191,40052:28194,40053:28198,40054:28199,40055:28200,40056:28202,40057:28204,40058:28206,40059:28208,40060:28209,40061:28211,40062:28213,40064:28214,40065:28215,40066:28217,40067:28219,40068:28220,40069:28221,40070:28222,40071:28223,40072:28224,40073:28225,40074:28226,40075:28229,40076:28230,40077:28231,40078:28232,40079:28233,40080:28234,40081:28235,40082:28236,40083:28239,40084:28240,40085:28241,40086:28242,40087:28245,40088:28247,40089:28249,40090:28250,40091:28252,40092:28253,40093:28254,40094:28256,40095:28257,40096:28258,40097:28259,40098:28260,40099:28261,40100:28262,40101:28263,40102:28264,40103:28265,40104:28266,40105:28268,40106:28269,40107:28271,40108:28272,40109:28273,40110:28274,40111:28275,40112:28276,40113:28277,40114:28278,40115:28279,40116:28280,40117:28281,40118:28282,40119:28283,40120:28284,40121:28285,40122:28288,40123:28289,40124:28290,40125:28292,40126:28295,40127:28296,40128:28298,40129:28299,40130:28300,40131:28301,40132:28302,40133:28305,40134:28306,40135:28307,40136:28308,40137:28309,40138:28310,40139:28311,40140:28313,40141:28314,40142:28315,40143:28317,40144:28318,40145:28320,40146:28321,40147:28323,40148:28324,40149:28326,40150:28328,40151:28329,40152:28331,40153:28332,40154:28333,40155:28334,40156:28336,40157:28339,40158:28341,40159:28344,40160:28345,40161:28348,40162:28350,40163:28351,40164:28352,40165:28355,40166:28356,40167:28357,40168:28358,40169:28360,40170:28361,40171:28362,40172:28364,40173:28365,40174:28366,40175:28368,40176:28370,40177:28374,40178:28376,40179:28377,40180:28379,40181:28380,40182:28381,40183:28387,40184:28391,40185:28394,40186:28395,40187:28396,40188:28397,40189:28398,40190:28399,40256:28400,40257:28401,40258:28402,40259:28403,40260:28405,40261:28406,40262:28407,40263:28408,40264:28410,40265:28411,40266:28412,40267:28413,40268:28414,40269:28415,40270:28416,40271:28417,40272:28419,40273:28420,40274:28421,40275:28423,40276:28424,40277:28426,40278:28427,40279:28428,40280:28429,40281:28430,40282:28432,40283:28433,40284:28434,40285:28438,40286:28439,40287:28440,40288:28441,40289:28442,40290:28443,40291:28444,40292:28445,40293:28446,40294:28447,40295:28449,40296:28450,40297:28451,40298:28453,40299:28454,40300:28455,40301:28456,40302:28460,40303:28462,40304:28464,40305:28466,40306:28468,40307:28469,40308:28471,40309:28472,40310:28473,40311:28474,40312:28475,40313:28476,40314:28477,40315:28479,40316:28480,40317:28481,40318:28482,40320:28483,40321:28484,40322:28485,40323:28488,40324:28489,40325:28490,40326:28492,40327:28494,40328:28495,40329:28496,40330:28497,40331:28498,40332:28499,40333:28500,40334:28501,40335:28502,40336:28503,40337:28505,40338:28506,40339:28507,40340:28509,40341:28511,40342:28512,40343:28513,40344:28515,40345:28516,40346:28517,40347:28519,40348:28520,40349:28521,40350:28522,40351:28523,40352:28524,40353:28527,40354:28528,40355:28529,40356:28531,40357:28533,40358:28534,40359:28535,40360:28537,40361:28539,40362:28541,40363:28542,40364:28543,40365:28544,40366:28545,40367:28546,40368:28547,40369:28549,40370:28550,40371:28551,40372:28554,40373:28555,40374:28559,40375:28560,40376:28561,40377:28562,40378:28563,40379:28564,40380:28565,40381:28566,40382:28567,40383:28568,40384:28569,40385:28570,40386:28571,40387:28573,40388:28574,40389:28575,40390:28576,40391:28578,40392:28579,40393:28580,40394:28581,40395:28582,40396:28584,40397:28585,40398:28586,40399:28587,40400:28588,40401:28589,40402:28590,40403:28591,40404:28592,40405:28593,40406:28594,40407:28596,40408:28597,40409:28599,40410:28600,40411:28602,40412:28603,40413:28604,40414:28605,40415:28606,40416:28607,40417:28609,40418:28611,40419:28612,40420:28613,40421:28614,40422:28615,40423:28616,40424:28618,40425:28619,40426:28620,40427:28621,40428:28622,40429:28623,40430:28624,40431:28627,40432:28628,40433:28629,40434:28630,40435:28631,40436:28632,40437:28633,40438:28634,40439:28635,40440:28636,40441:28637,40442:28639,40443:28642,40444:28643,40445:28644,40446:28645,40512:28646,40513:28647,40514:28648,40515:28649,40516:28650,40517:28651,40518:28652,40519:28653,40520:28656,40521:28657,40522:28658,40523:28659,40524:28660,40525:28661,40526:28662,40527:28663,40528:28664,40529:28665,40530:28666,40531:28667,40532:28668,40533:28669,40534:28670,40535:28671,40536:28672,40537:28673,40538:28674,40539:28675,40540:28676,40541:28677,40542:28678,40543:28679,40544:28680,40545:28681,40546:28682,40547:28683,40548:28684,40549:28685,40550:28686,40551:28687,40552:28688,40553:28690,40554:28691,40555:28692,40556:28693,40557:28694,40558:28695,40559:28696,40560:28697,40561:28700,40562:28701,40563:28702,40564:28703,40565:28704,40566:28705,40567:28706,40568:28708,40569:28709,40570:28710,40571:28711,40572:28712,40573:28713,40574:28714,40576:28715,40577:28716,40578:28717,40579:28718,40580:28719,40581:28720,40582:28721,40583:28722,40584:28723,40585:28724,40586:28726,40587:28727,40588:28728,40589:28730,40590:28731,40591:28732,40592:28733,40593:28734,40594:28735,40595:28736,40596:28737,40597:28738,40598:28739,40599:28740,40600:28741,40601:28742,40602:28743,40603:28744,40604:28745,40605:28746,40606:28747,40607:28749,40608:28750,40609:28752,40610:28753,40611:28754,40612:28755,40613:28756,40614:28757,40615:28758,40616:28759,40617:28760,40618:28761,40619:28762,40620:28763,40621:28764,40622:28765,40623:28767,40624:28768,40625:28769,40626:28770,40627:28771,40628:28772,40629:28773,40630:28774,40631:28775,40632:28776,40633:28777,40634:28778,40635:28782,40636:28785,40637:28786,40638:28787,40639:28788,40640:28791,40641:28793,40642:28794,40643:28795,40644:28797,40645:28801,40646:28802,40647:28803,40648:28804,40649:28806,40650:28807,40651:28808,40652:28811,40653:28812,40654:28813,40655:28815,40656:28816,40657:28817,40658:28819,40659:28823,40660:28824,40661:28826,40662:28827,40663:28830,40664:28831,40665:28832,40666:28833,40667:28834,40668:28835,40669:28836,40670:28837,40671:28838,40672:28839,40673:28840,40674:28841,40675:28842,40676:28848,40677:28850,40678:28852,40679:28853,40680:28854,40681:28858,40682:28862,40683:28863,40684:28868,40685:28869,40686:28870,40687:28871,40688:28873,40689:28875,40690:28876,40691:28877,40692:28878,40693:28879,40694:28880,40695:28881,40696:28882,40697:28883,40698:28884,40699:28885,40700:28886,40701:28887,40702:28890,40768:28892,40769:28893,40770:28894,40771:28896,40772:28897,40773:28898,40774:28899,40775:28901,40776:28906,40777:28910,40778:28912,40779:28913,40780:28914,40781:28915,40782:28916,40783:28917,40784:28918,40785:28920,40786:28922,40787:28923,40788:28924,40789:28926,40790:28927,40791:28928,40792:28929,40793:28930,40794:28931,40795:28932,40796:28933,40797:28934,40798:28935,40799:28936,40800:28939,40801:28940,40802:28941,40803:28942,40804:28943,40805:28945,40806:28946,40807:28948,40808:28951,40809:28955,40810:28956,40811:28957,40812:28958,40813:28959,40814:28960,40815:28961,40816:28962,40817:28963,40818:28964,40819:28965,40820:28967,40821:28968,40822:28969,40823:28970,40824:28971,40825:28972,40826:28973,40827:28974,40828:28978,40829:28979,40830:28980,40832:28981,40833:28983,40834:28984,40835:28985,40836:28986,40837:28987,40838:28988,40839:28989,40840:28990,40841:28991,40842:28992,40843:28993,40844:28994,40845:28995,40846:28996,40847:28998,40848:28999,40849:29000,40850:29001,40851:29003,40852:29005,40853:29007,40854:29008,40855:29009,40856:29010,40857:29011,40858:29012,40859:29013,40860:29014,40861:29015,40862:29016,40863:29017,40864:29018,40865:29019,40866:29021,40867:29023,40868:29024,40869:29025,40870:29026,40871:29027,40872:29029,40873:29033,40874:29034,40875:29035,40876:29036,40877:29037,40878:29039,40879:29040,40880:29041,40881:29044,40882:29045,40883:29046,40884:29047,40885:29049,40886:29051,40887:29052,40888:29054,40889:29055,40890:29056,40891:29057,40892:29058,40893:29059,40894:29061,40895:29062,40896:29063,40897:29064,40898:29065,40899:29067,40900:29068,40901:29069,40902:29070,40903:29072,40904:29073,40905:29074,40906:29075,40907:29077,40908:29078,40909:29079,40910:29082,40911:29083,40912:29084,40913:29085,40914:29086,40915:29089,40916:29090,40917:29091,40918:29092,40919:29093,40920:29094,40921:29095,40922:29097,40923:29098,40924:29099,40925:29101,40926:29102,40927:29103,40928:29104,40929:29105,40930:29106,40931:29108,40932:29110,40933:29111,40934:29112,40935:29114,40936:29115,40937:29116,40938:29117,40939:29118,40940:29119,40941:29120,40942:29121,40943:29122,40944:29124,40945:29125,40946:29126,40947:29127,40948:29128,40949:29129,40950:29130,40951:29131,40952:29132,40953:29133,40954:29135,40955:29136,40956:29137,40957:29138,40958:29139,41024:29142,41025:29143,41026:29144,41027:29145,41028:29146,41029:29147,41030:29148,41031:29149,41032:29150,41033:29151,41034:29153,41035:29154,41036:29155,41037:29156,41038:29158,41039:29160,41040:29161,41041:29162,41042:29163,41043:29164,41044:29165,41045:29167,41046:29168,41047:29169,41048:29170,41049:29171,41050:29172,41051:29173,41052:29174,41053:29175,41054:29176,41055:29178,41056:29179,41057:29180,41058:29181,41059:29182,41060:29183,41061:29184,41062:29185,41063:29186,41064:29187,41065:29188,41066:29189,41067:29191,41068:29192,41069:29193,41070:29194,41071:29195,41072:29196,41073:29197,41074:29198,41075:29199,41076:29200,41077:29201,41078:29202,41079:29203,41080:29204,41081:29205,41082:29206,41083:29207,41084:29208,41085:29209,41086:29210,41088:29211,41089:29212,41090:29214,41091:29215,41092:29216,41093:29217,41094:29218,41095:29219,41096:29220,41097:29221,41098:29222,41099:29223,41100:29225,41101:29227,41102:29229,41103:29230,41104:29231,41105:29234,41106:29235,41107:29236,41108:29242,41109:29244,41110:29246,41111:29248,41112:29249,41113:29250,41114:29251,41115:29252,41116:29253,41117:29254,41118:29257,41119:29258,41120:29259,41121:29262,41122:29263,41123:29264,41124:29265,41125:29267,41126:29268,41127:29269,41128:29271,41129:29272,41130:29274,41131:29276,41132:29278,41133:29280,41134:29283,41135:29284,41136:29285,41137:29288,41138:29290,41139:29291,41140:29292,41141:29293,41142:29296,41143:29297,41144:29299,41145:29300,41146:29302,41147:29303,41148:29304,41149:29307,41150:29308,41151:29309,41152:29314,41153:29315,41154:29317,41155:29318,41156:29319,41157:29320,41158:29321,41159:29324,41160:29326,41161:29328,41162:29329,41163:29331,41164:29332,41165:29333,41166:29334,41167:29335,41168:29336,41169:29337,41170:29338,41171:29339,41172:29340,41173:29341,41174:29342,41175:29344,41176:29345,41177:29346,41178:29347,41179:29348,41180:29349,41181:29350,41182:29351,41183:29352,41184:29353,41185:29354,41186:29355,41187:29358,41188:29361,41189:29362,41190:29363,41191:29365,41192:29370,41193:29371,41194:29372,41195:29373,41196:29374,41197:29375,41198:29376,41199:29381,41200:29382,41201:29383,41202:29385,41203:29386,41204:29387,41205:29388,41206:29391,41207:29393,41208:29395,41209:29396,41210:29397,41211:29398,41212:29400,41213:29402,41214:29403,41280:58566,41281:58567,41282:58568,41283:58569,41284:58570,41285:58571,41286:58572,41287:58573,41288:58574,41289:58575,41290:58576,41291:58577,41292:58578,41293:58579,41294:58580,41295:58581,41296:58582,41297:58583,41298:58584,41299:58585,41300:58586,41301:58587,41302:58588,41303:58589,41304:58590,41305:58591,41306:58592,41307:58593,41308:58594,41309:58595,41310:58596,41311:58597,41312:58598,41313:58599,41314:58600,41315:58601,41316:58602,41317:58603,41318:58604,41319:58605,41320:58606,41321:58607,41322:58608,41323:58609,41324:58610,41325:58611,41326:58612,41327:58613,41328:58614,41329:58615,41330:58616,41331:58617,41332:58618,41333:58619,41334:58620,41335:58621,41336:58622,41337:58623,41338:58624,41339:58625,41340:58626,41341:58627,41342:58628,41344:58629,41345:58630,41346:58631,41347:58632,41348:58633,41349:58634,41350:58635,41351:58636,41352:58637,41353:58638,41354:58639,41355:58640,41356:58641,41357:58642,41358:58643,41359:58644,41360:58645,41361:58646,41362:58647,41363:58648,41364:58649,41365:58650,41366:58651,41367:58652,41368:58653,41369:58654,41370:58655,41371:58656,41372:58657,41373:58658,41374:58659,41375:58660,41376:58661,41377:12288,41378:12289,41379:12290,41380:183,41381:713,41382:711,41383:168,41384:12291,41385:12293,41386:8212,41387:65374,41388:8214,41389:8230,41390:8216,41391:8217,41392:8220,41393:8221,41394:12308,41395:12309,41396:12296,41397:12297,41398:12298,41399:12299,41400:12300,41401:12301,41402:12302,41403:12303,41404:12310,41405:12311,41406:12304,41407:12305,41408:177,41409:215,41410:247,41411:8758,41412:8743,41413:8744,41414:8721,41415:8719,41416:8746,41417:8745,41418:8712,41419:8759,41420:8730,41421:8869,41422:8741,41423:8736,41424:8978,41425:8857,41426:8747,41427:8750,41428:8801,41429:8780,41430:8776,41431:8765,41432:8733,41433:8800,41434:8814,41435:8815,41436:8804,41437:8805,41438:8734,41439:8757,41440:8756,41441:9794,41442:9792,41443:176,41444:8242,41445:8243,41446:8451,41447:65284,41448:164,41449:65504,41450:65505,41451:8240,41452:167,41453:8470,41454:9734,41455:9733,41456:9675,41457:9679,41458:9678,41459:9671,41460:9670,41461:9633,41462:9632,41463:9651,41464:9650,41465:8251,41466:8594,41467:8592,41468:8593,41469:8595,41470:12307,41536:58662,41537:58663,41538:58664,41539:58665,41540:58666,41541:58667,41542:58668,41543:58669,41544:58670,41545:58671,41546:58672,41547:58673,41548:58674,41549:58675,41550:58676,41551:58677,41552:58678,41553:58679,41554:58680,41555:58681,41556:58682,41557:58683,41558:58684,41559:58685,41560:58686,41561:58687,41562:58688,41563:58689,41564:58690,41565:58691,41566:58692,41567:58693,41568:58694,41569:58695,41570:58696,41571:58697,41572:58698,41573:58699,41574:58700,41575:58701,41576:58702,41577:58703,41578:58704,41579:58705,41580:58706,41581:58707,41582:58708,41583:58709,41584:58710,41585:58711,41586:58712,41587:58713,41588:58714,41589:58715,41590:58716,41591:58717,41592:58718,41593:58719,41594:58720,41595:58721,41596:58722,41597:58723,41598:58724,41600:58725,41601:58726,41602:58727,41603:58728,41604:58729,41605:58730,41606:58731,41607:58732,41608:58733,41609:58734,41610:58735,41611:58736,41612:58737,41613:58738,41614:58739,41615:58740,41616:58741,41617:58742,41618:58743,41619:58744,41620:58745,41621:58746,41622:58747,41623:58748,41624:58749,41625:58750,41626:58751,41627:58752,41628:58753,41629:58754,41630:58755,41631:58756,41632:58757,41633:8560,41634:8561,41635:8562,41636:8563,41637:8564,41638:8565,41639:8566,41640:8567,41641:8568,41642:8569,41643:59238,41644:59239,41645:59240,41646:59241,41647:59242,41648:59243,41649:9352,41650:9353,41651:9354,41652:9355,41653:9356,41654:9357,41655:9358,41656:9359,41657:9360,41658:9361,41659:9362,41660:9363,41661:9364,41662:9365,41663:9366,41664:9367,41665:9368,41666:9369,41667:9370,41668:9371,41669:9332,41670:9333,41671:9334,41672:9335,41673:9336,41674:9337,41675:9338,41676:9339,41677:9340,41678:9341,41679:9342,41680:9343,41681:9344,41682:9345,41683:9346,41684:9347,41685:9348,41686:9349,41687:9350,41688:9351,41689:9312,41690:9313,41691:9314,41692:9315,41693:9316,41694:9317,41695:9318,41696:9319,41697:9320,41698:9321,41699:8364,41700:59245,41701:12832,41702:12833,41703:12834,41704:12835,41705:12836,41706:12837,41707:12838,41708:12839,41709:12840,41710:12841,41711:59246,41712:59247,41713:8544,41714:8545,41715:8546,41716:8547,41717:8548,41718:8549,41719:8550,41720:8551,41721:8552,41722:8553,41723:8554,41724:8555,41725:59248,41726:59249,41792:58758,41793:58759,41794:58760,41795:58761,41796:58762,41797:58763,41798:58764,41799:58765,41800:58766,41801:58767,41802:58768,41803:58769,41804:58770,41805:58771,41806:58772,41807:58773,41808:58774,41809:58775,41810:58776,41811:58777,41812:58778,41813:58779,41814:58780,41815:58781,41816:58782,41817:58783,41818:58784,41819:58785,41820:58786,41821:58787,41822:58788,41823:58789,41824:58790,41825:58791,41826:58792,41827:58793,41828:58794,41829:58795,41830:58796,41831:58797,41832:58798,41833:58799,41834:58800,41835:58801,41836:58802,41837:58803,41838:58804,41839:58805,41840:58806,41841:58807,41842:58808,41843:58809,41844:58810,41845:58811,41846:58812,41847:58813,41848:58814,41849:58815,41850:58816,41851:58817,41852:58818,41853:58819,41854:58820,41856:58821,41857:58822,41858:58823,41859:58824,41860:58825,41861:58826,41862:58827,41863:58828,41864:58829,41865:58830,41866:58831,41867:58832,41868:58833,41869:58834,41870:58835,41871:58836,41872:58837,41873:58838,41874:58839,41875:58840,41876:58841,41877:58842,41878:58843,41879:58844,41880:58845,41881:58846,41882:58847,41883:58848,41884:58849,41885:58850,41886:58851,41887:58852,41888:58853,41889:65281,41890:65282,41891:65283,41892:65509,41893:65285,41894:65286,41895:65287,41896:65288,41897:65289,41898:65290,41899:65291,41900:65292,41901:65293,41902:65294,41903:65295,41904:65296,41905:65297,41906:65298,41907:65299,41908:65300,41909:65301,41910:65302,41911:65303,41912:65304,41913:65305,41914:65306,41915:65307,41916:65308,41917:65309,41918:65310,41919:65311,41920:65312,41921:65313,41922:65314,41923:65315,41924:65316,41925:65317,41926:65318,41927:65319,41928:65320,41929:65321,41930:65322,41931:65323,41932:65324,41933:65325,41934:65326,41935:65327,41936:65328,41937:65329,41938:65330,41939:65331,41940:65332,41941:65333,41942:65334,41943:65335,41944:65336,41945:65337,41946:65338,41947:65339,41948:65340,41949:65341,41950:65342,41951:65343,41952:65344,41953:65345,41954:65346,41955:65347,41956:65348,41957:65349,41958:65350,41959:65351,41960:65352,41961:65353,41962:65354,41963:65355,41964:65356,41965:65357,41966:65358,41967:65359,41968:65360,41969:65361,41970:65362,41971:65363,41972:65364,41973:65365,41974:65366,41975:65367,41976:65368,41977:65369,41978:65370,41979:65371,41980:65372,41981:65373,41982:65507,42048:58854,42049:58855,42050:58856,42051:58857,42052:58858,42053:58859,42054:58860,42055:58861,42056:58862,42057:58863,42058:58864,42059:58865,42060:58866,42061:58867,42062:58868,42063:58869,42064:58870,42065:58871,42066:58872,42067:58873,42068:58874,42069:58875,42070:58876,42071:58877,42072:58878,42073:58879,42074:58880,42075:58881,42076:58882,42077:58883,42078:58884,42079:58885,42080:58886,42081:58887,42082:58888,42083:58889,42084:58890,42085:58891,42086:58892,42087:58893,42088:58894,42089:58895,42090:58896,42091:58897,42092:58898,42093:58899,42094:58900,42095:58901,42096:58902,42097:58903,42098:58904,42099:58905,42100:58906,42101:58907,42102:58908,42103:58909,42104:58910,42105:58911,42106:58912,42107:58913,42108:58914,42109:58915,42110:58916,42112:58917,42113:58918,42114:58919,42115:58920,42116:58921,42117:58922,42118:58923,42119:58924,42120:58925,42121:58926,42122:58927,42123:58928,42124:58929,42125:58930,42126:58931,42127:58932,42128:58933,42129:58934,42130:58935,42131:58936,42132:58937,42133:58938,42134:58939,42135:58940,42136:58941,42137:58942,42138:58943,42139:58944,42140:58945,42141:58946,42142:58947,42143:58948,42144:58949,42145:12353,42146:12354,42147:12355,42148:12356,42149:12357,42150:12358,42151:12359,42152:12360,42153:12361,42154:12362,42155:12363,42156:12364,42157:12365,42158:12366,42159:12367,42160:12368,42161:12369,42162:12370,42163:12371,42164:12372,42165:12373,42166:12374,42167:12375,42168:12376,42169:12377,42170:12378,42171:12379,42172:12380,42173:12381,42174:12382,42175:12383,42176:12384,42177:12385,42178:12386,42179:12387,42180:12388,42181:12389,42182:12390,42183:12391,42184:12392,42185:12393,42186:12394,42187:12395,42188:12396,42189:12397,42190:12398,42191:12399,42192:12400,42193:12401,42194:12402,42195:12403,42196:12404,42197:12405,42198:12406,42199:12407,42200:12408,42201:12409,42202:12410,42203:12411,42204:12412,42205:12413,42206:12414,42207:12415,42208:12416,42209:12417,42210:12418,42211:12419,42212:12420,42213:12421,42214:12422,42215:12423,42216:12424,42217:12425,42218:12426,42219:12427,42220:12428,42221:12429,42222:12430,42223:12431,42224:12432,42225:12433,42226:12434,42227:12435,42228:59250,42229:59251,42230:59252,42231:59253,42232:59254,42233:59255,42234:59256,42235:59257,42236:59258,42237:59259,42238:59260,42304:58950,42305:58951,42306:58952,42307:58953,42308:58954,42309:58955,42310:58956,42311:58957,42312:58958,42313:58959,42314:58960,42315:58961,42316:58962,42317:58963,42318:58964,42319:58965,42320:58966,42321:58967,42322:58968,42323:58969,42324:58970,42325:58971,42326:58972,42327:58973,42328:58974,42329:58975,42330:58976,42331:58977,42332:58978,42333:58979,42334:58980,42335:58981,42336:58982,42337:58983,42338:58984,42339:58985,42340:58986,42341:58987,42342:58988,42343:58989,42344:58990,42345:58991,42346:58992,42347:58993,42348:58994,42349:58995,42350:58996,42351:58997,42352:58998,42353:58999,42354:59000,42355:59001,42356:59002,42357:59003,42358:59004,42359:59005,42360:59006,42361:59007,42362:59008,42363:59009,42364:59010,42365:59011,42366:59012,42368:59013,42369:59014,42370:59015,42371:59016,42372:59017,42373:59018,42374:59019,42375:59020,42376:59021,42377:59022,42378:59023,42379:59024,42380:59025,42381:59026,42382:59027,42383:59028,42384:59029,42385:59030,42386:59031,42387:59032,42388:59033,42389:59034,42390:59035,42391:59036,42392:59037,42393:59038,42394:59039,42395:59040,42396:59041,42397:59042,42398:59043,42399:59044,42400:59045,42401:12449,42402:12450,42403:12451,42404:12452,42405:12453,42406:12454,42407:12455,42408:12456,42409:12457,42410:12458,42411:12459,42412:12460,42413:12461,42414:12462,42415:12463,42416:12464,42417:12465,42418:12466,42419:12467,42420:12468,42421:12469,42422:12470,42423:12471,42424:12472,42425:12473,42426:12474,42427:12475,42428:12476,42429:12477,42430:12478,42431:12479,42432:12480,42433:12481,42434:12482,42435:12483,42436:12484,42437:12485,42438:12486,42439:12487,42440:12488,42441:12489,42442:12490,42443:12491,42444:12492,42445:12493,42446:12494,42447:12495,42448:12496,42449:12497,42450:12498,42451:12499,42452:12500,42453:12501,42454:12502,42455:12503,42456:12504,42457:12505,42458:12506,42459:12507,42460:12508,42461:12509,42462:12510,42463:12511,42464:12512,42465:12513,42466:12514,42467:12515,42468:12516,42469:12517,42470:12518,42471:12519,42472:12520,42473:12521,42474:12522,42475:12523,42476:12524,42477:12525,42478:12526,42479:12527,42480:12528,42481:12529,42482:12530,42483:12531,42484:12532,42485:12533,42486:12534,42487:59261,42488:59262,42489:59263,42490:59264,42491:59265,42492:59266,42493:59267,42494:59268,42560:59046,42561:59047,42562:59048,42563:59049,42564:59050,42565:59051,42566:59052,42567:59053,42568:59054,42569:59055,42570:59056,42571:59057,42572:59058,42573:59059,42574:59060,42575:59061,42576:59062,42577:59063,42578:59064,42579:59065,42580:59066,42581:59067,42582:59068,42583:59069,42584:59070,42585:59071,42586:59072,42587:59073,42588:59074,42589:59075,42590:59076,42591:59077,42592:59078,42593:59079,42594:59080,42595:59081,42596:59082,42597:59083,42598:59084,42599:59085,42600:59086,42601:59087,42602:59088,42603:59089,42604:59090,42605:59091,42606:59092,42607:59093,42608:59094,42609:59095,42610:59096,42611:59097,42612:59098,42613:59099,42614:59100,42615:59101,42616:59102,42617:59103,42618:59104,42619:59105,42620:59106,42621:59107,42622:59108,42624:59109,42625:59110,42626:59111,42627:59112,42628:59113,42629:59114,42630:59115,42631:59116,42632:59117,42633:59118,42634:59119,42635:59120,42636:59121,42637:59122,42638:59123,42639:59124,42640:59125,42641:59126,42642:59127,42643:59128,42644:59129,42645:59130,42646:59131,42647:59132,42648:59133,42649:59134,42650:59135,42651:59136,42652:59137,42653:59138,42654:59139,42655:59140,42656:59141,42657:913,42658:914,42659:915,42660:916,42661:917,42662:918,42663:919,42664:920,42665:921,42666:922,42667:923,42668:924,42669:925,42670:926,42671:927,42672:928,42673:929,42674:931,42675:932,42676:933,42677:934,42678:935,42679:936,42680:937,42681:59269,42682:59270,42683:59271,42684:59272,42685:59273,42686:59274,42687:59275,42688:59276,42689:945,42690:946,42691:947,42692:948,42693:949,42694:950,42695:951,42696:952,42697:953,42698:954,42699:955,42700:956,42701:957,42702:958,42703:959,42704:960,42705:961,42706:963,42707:964,42708:965,42709:966,42710:967,42711:968,42712:969,42713:59277,42714:59278,42715:59279,42716:59280,42717:59281,42718:59282,42719:59283,42720:65077,42721:65078,42722:65081,42723:65082,42724:65087,42725:65088,42726:65085,42727:65086,42728:65089,42729:65090,42730:65091,42731:65092,42732:59284,42733:59285,42734:65083,42735:65084,42736:65079,42737:65080,42738:65073,42739:59286,42740:65075,42741:65076,42742:59287,42743:59288,42744:59289,42745:59290,42746:59291,42747:59292,42748:59293,42749:59294,42750:59295,42816:59142,42817:59143,42818:59144,42819:59145,42820:59146,42821:59147,42822:59148,42823:59149,42824:59150,42825:59151,42826:59152,42827:59153,42828:59154,42829:59155,42830:59156,42831:59157,42832:59158,42833:59159,42834:59160,42835:59161,42836:59162,42837:59163,42838:59164,42839:59165,42840:59166,42841:59167,42842:59168,42843:59169,42844:59170,42845:59171,42846:59172,42847:59173,42848:59174,42849:59175,42850:59176,42851:59177,42852:59178,42853:59179,42854:59180,42855:59181,42856:59182,42857:59183,42858:59184,42859:59185,42860:59186,42861:59187,42862:59188,42863:59189,42864:59190,42865:59191,42866:59192,42867:59193,42868:59194,42869:59195,42870:59196,42871:59197,42872:59198,42873:59199,42874:59200,42875:59201,42876:59202,42877:59203,42878:59204,42880:59205,42881:59206,42882:59207,42883:59208,42884:59209,42885:59210,42886:59211,42887:59212,42888:59213,42889:59214,42890:59215,42891:59216,42892:59217,42893:59218,42894:59219,42895:59220,42896:59221,42897:59222,42898:59223,42899:59224,42900:59225,42901:59226,42902:59227,42903:59228,42904:59229,42905:59230,42906:59231,42907:59232,42908:59233,42909:59234,42910:59235,42911:59236,42912:59237,42913:1040,42914:1041,42915:1042,42916:1043,42917:1044,42918:1045,42919:1025,42920:1046,42921:1047,42922:1048,42923:1049,42924:1050,42925:1051,42926:1052,42927:1053,42928:1054,42929:1055,42930:1056,42931:1057,42932:1058,42933:1059,42934:1060,42935:1061,42936:1062,42937:1063,42938:1064,42939:1065,42940:1066,42941:1067,42942:1068,42943:1069,42944:1070,42945:1071,42946:59296,42947:59297,42948:59298,42949:59299,42950:59300,42951:59301,42952:59302,42953:59303,42954:59304,42955:59305,42956:59306,42957:59307,42958:59308,42959:59309,42960:59310,42961:1072,42962:1073,42963:1074,42964:1075,42965:1076,42966:1077,42967:1105,42968:1078,42969:1079,42970:1080,42971:1081,42972:1082,42973:1083,42974:1084,42975:1085,42976:1086,42977:1087,42978:1088,42979:1089,42980:1090,42981:1091,42982:1092,42983:1093,42984:1094,42985:1095,42986:1096,42987:1097,42988:1098,42989:1099,42990:1100,42991:1101,42992:1102,42993:1103,42994:59311,42995:59312,42996:59313,42997:59314,42998:59315,42999:59316,43000:59317,43001:59318,43002:59319,43003:59320,43004:59321,43005:59322,43006:59323,43072:714,43073:715,43074:729,43075:8211,43076:8213,43077:8229,43078:8245,43079:8453,43080:8457,43081:8598,43082:8599,43083:8600,43084:8601,43085:8725,43086:8735,43087:8739,43088:8786,43089:8806,43090:8807,43091:8895,43092:9552,43093:9553,43094:9554,43095:9555,43096:9556,43097:9557,43098:9558,43099:9559,43100:9560,43101:9561,43102:9562,43103:9563,43104:9564,43105:9565,43106:9566,43107:9567,43108:9568,43109:9569,43110:9570,43111:9571,43112:9572,43113:9573,43114:9574,43115:9575,43116:9576,43117:9577,43118:9578,43119:9579,43120:9580,43121:9581,43122:9582,43123:9583,43124:9584,43125:9585,43126:9586,43127:9587,43128:9601,43129:9602,43130:9603,43131:9604,43132:9605,43133:9606,43134:9607,43136:9608,43137:9609,43138:9610,43139:9611,43140:9612,43141:9613,43142:9614,43143:9615,43144:9619,43145:9620,43146:9621,43147:9660,43148:9661,43149:9698,43150:9699,43151:9700,43152:9701,43153:9737,43154:8853,43155:12306,43156:12317,43157:12318,43158:59324,43159:59325,43160:59326,43161:59327,43162:59328,43163:59329,43164:59330,43165:59331,43166:59332,43167:59333,43168:59334,43169:257,43170:225,43171:462,43172:224,43173:275,43174:233,43175:283,43176:232,43177:299,43178:237,43179:464,43180:236,43181:333,43182:243,43183:466,43184:242,43185:363,43186:250,43187:468,43188:249,43189:470,43190:472,43191:474,43192:476,43193:252,43194:234,43195:593,43196:59335,43197:324,43198:328,43199:505,43200:609,43201:59337,43202:59338,43203:59339,43204:59340,43205:12549,43206:12550,43207:12551,43208:12552,43209:12553,43210:12554,43211:12555,43212:12556,43213:12557,43214:12558,43215:12559,43216:12560,43217:12561,43218:12562,43219:12563,43220:12564,43221:12565,43222:12566,43223:12567,43224:12568,43225:12569,43226:12570,43227:12571,43228:12572,43229:12573,43230:12574,43231:12575,43232:12576,43233:12577,43234:12578,43235:12579,43236:12580,43237:12581,43238:12582,43239:12583,43240:12584,43241:12585,43242:59341,43243:59342,43244:59343,43245:59344,43246:59345,43247:59346,43248:59347,43249:59348,43250:59349,43251:59350,43252:59351,43253:59352,43254:59353,43255:59354,43256:59355,43257:59356,43258:59357,43259:59358,43260:59359,43261:59360,43262:59361,43328:12321,43329:12322,43330:12323,43331:12324,43332:12325,43333:12326,43334:12327,43335:12328,43336:12329,43337:12963,43338:13198,43339:13199,43340:13212,43341:13213,43342:13214,43343:13217,43344:13252,43345:13262,43346:13265,43347:13266,43348:13269,43349:65072,43350:65506,43351:65508,43352:59362,43353:8481,43354:12849,43355:59363,43356:8208,43357:59364,43358:59365,43359:59366,43360:12540,43361:12443,43362:12444,43363:12541,43364:12542,43365:12294,43366:12445,43367:12446,43368:65097,43369:65098,43370:65099,43371:65100,43372:65101,43373:65102,43374:65103,43375:65104,43376:65105,43377:65106,43378:65108,43379:65109,43380:65110,43381:65111,43382:65113,43383:65114,43384:65115,43385:65116,43386:65117,43387:65118,43388:65119,43389:65120,43390:65121,43392:65122,43393:65123,43394:65124,43395:65125,43396:65126,43397:65128,43398:65129,43399:65130,43400:65131,43401:12350,43402:12272,43403:12273,43404:12274,43405:12275,43406:12276,43407:12277,43408:12278,43409:12279,43410:12280,43411:12281,43412:12282,43413:12283,43414:12295,43415:59380,43416:59381,43417:59382,43418:59383,43419:59384,43420:59385,43421:59386,43422:59387,43423:59388,43424:59389,43425:59390,43426:59391,43427:59392,43428:9472,43429:9473,43430:9474,43431:9475,43432:9476,43433:9477,43434:9478,43435:9479,43436:9480,43437:9481,43438:9482,43439:9483,43440:9484,43441:9485,43442:9486,43443:9487,43444:9488,43445:9489,43446:9490,43447:9491,43448:9492,43449:9493,43450:9494,43451:9495,43452:9496,43453:9497,43454:9498,43455:9499,43456:9500,43457:9501,43458:9502,43459:9503,43460:9504,43461:9505,43462:9506,43463:9507,43464:9508,43465:9509,43466:9510,43467:9511,43468:9512,43469:9513,43470:9514,43471:9515,43472:9516,43473:9517,43474:9518,43475:9519,43476:9520,43477:9521,43478:9522,43479:9523,43480:9524,43481:9525,43482:9526,43483:9527,43484:9528,43485:9529,43486:9530,43487:9531,43488:9532,43489:9533,43490:9534,43491:9535,43492:9536,43493:9537,43494:9538,43495:9539,43496:9540,43497:9541,43498:9542,43499:9543,43500:9544,43501:9545,43502:9546,43503:9547,43504:59393,43505:59394,43506:59395,43507:59396,43508:59397,43509:59398,43510:59399,43511:59400,43512:59401,43513:59402,43514:59403,43515:59404,43516:59405,43517:59406,43518:59407,43584:29404,43585:29405,43586:29407,43587:29410,43588:29411,43589:29412,43590:29413,43591:29414,43592:29415,43593:29418,43594:29419,43595:29429,43596:29430,43597:29433,43598:29437,43599:29438,43600:29439,43601:29440,43602:29442,43603:29444,43604:29445,43605:29446,43606:29447,43607:29448,43608:29449,43609:29451,43610:29452,43611:29453,43612:29455,43613:29456,43614:29457,43615:29458,43616:29460,43617:29464,43618:29465,43619:29466,43620:29471,43621:29472,43622:29475,43623:29476,43624:29478,43625:29479,43626:29480,43627:29485,43628:29487,43629:29488,43630:29490,43631:29491,43632:29493,43633:29494,43634:29498,43635:29499,43636:29500,43637:29501,43638:29504,43639:29505,43640:29506,43641:29507,43642:29508,43643:29509,43644:29510,43645:29511,43646:29512,43648:29513,43649:29514,43650:29515,43651:29516,43652:29518,43653:29519,43654:29521,43655:29523,43656:29524,43657:29525,43658:29526,43659:29528,43660:29529,43661:29530,43662:29531,43663:29532,43664:29533,43665:29534,43666:29535,43667:29537,43668:29538,43669:29539,43670:29540,43671:29541,43672:29542,43673:29543,43674:29544,43675:29545,43676:29546,43677:29547,43678:29550,43679:29552,43680:29553,43681:57344,43682:57345,43683:57346,43684:57347,43685:57348,43686:57349,43687:57350,43688:57351,43689:57352,43690:57353,43691:57354,43692:57355,43693:57356,43694:57357,43695:57358,43696:57359,43697:57360,43698:57361,43699:57362,43700:57363,43701:57364,43702:57365,43703:57366,43704:57367,43705:57368,43706:57369,43707:57370,43708:57371,43709:57372,43710:57373,43711:57374,43712:57375,43713:57376,43714:57377,43715:57378,43716:57379,43717:57380,43718:57381,43719:57382,43720:57383,43721:57384,43722:57385,43723:57386,43724:57387,43725:57388,43726:57389,43727:57390,43728:57391,43729:57392,43730:57393,43731:57394,43732:57395,43733:57396,43734:57397,43735:57398,43736:57399,43737:57400,43738:57401,43739:57402,43740:57403,43741:57404,43742:57405,43743:57406,43744:57407,43745:57408,43746:57409,43747:57410,43748:57411,43749:57412,43750:57413,43751:57414,43752:57415,43753:57416,43754:57417,43755:57418,43756:57419,43757:57420,43758:57421,43759:57422,43760:57423,43761:57424,43762:57425,43763:57426,43764:57427,43765:57428,43766:57429,43767:57430,43768:57431,43769:57432,43770:57433,43771:57434,43772:57435,43773:57436,43774:57437,43840:29554,43841:29555,43842:29556,43843:29557,43844:29558,43845:29559,43846:29560,43847:29561,43848:29562,43849:29563,43850:29564,43851:29565,43852:29567,43853:29568,43854:29569,43855:29570,43856:29571,43857:29573,43858:29574,43859:29576,43860:29578,43861:29580,43862:29581,43863:29583,43864:29584,43865:29586,43866:29587,43867:29588,43868:29589,43869:29591,43870:29592,43871:29593,43872:29594,43873:29596,43874:29597,43875:29598,43876:29600,43877:29601,43878:29603,43879:29604,43880:29605,43881:29606,43882:29607,43883:29608,43884:29610,43885:29612,43886:29613,43887:29617,43888:29620,43889:29621,43890:29622,43891:29624,43892:29625,43893:29628,43894:29629,43895:29630,43896:29631,43897:29633,43898:29635,43899:29636,43900:29637,43901:29638,43902:29639,43904:29643,43905:29644,43906:29646,43907:29650,43908:29651,43909:29652,43910:29653,43911:29654,43912:29655,43913:29656,43914:29658,43915:29659,43916:29660,43917:29661,43918:29663,43919:29665,43920:29666,43921:29667,43922:29668,43923:29670,43924:29672,43925:29674,43926:29675,43927:29676,43928:29678,43929:29679,43930:29680,43931:29681,43932:29683,43933:29684,43934:29685,43935:29686,43936:29687,43937:57438,43938:57439,43939:57440,43940:57441,43941:57442,43942:57443,43943:57444,43944:57445,43945:57446,43946:57447,43947:57448,43948:57449,43949:57450,43950:57451,43951:57452,43952:57453,43953:57454,43954:57455,43955:57456,43956:57457,43957:57458,43958:57459,43959:57460,43960:57461,43961:57462,43962:57463,43963:57464,43964:57465,43965:57466,43966:57467,43967:57468,43968:57469,43969:57470,43970:57471,43971:57472,43972:57473,43973:57474,43974:57475,43975:57476,43976:57477,43977:57478,43978:57479,43979:57480,43980:57481,43981:57482,43982:57483,43983:57484,43984:57485,43985:57486,43986:57487,43987:57488,43988:57489,43989:57490,43990:57491,43991:57492,43992:57493,43993:57494,43994:57495,43995:57496,43996:57497,43997:57498,43998:57499,43999:57500,44000:57501,44001:57502,44002:57503,44003:57504,44004:57505,44005:57506,44006:57507,44007:57508,44008:57509,44009:57510,44010:57511,44011:57512,44012:57513,44013:57514,44014:57515,44015:57516,44016:57517,44017:57518,44018:57519,44019:57520,44020:57521,44021:57522,44022:57523,44023:57524,44024:57525,44025:57526,44026:57527,44027:57528,44028:57529,44029:57530,44030:57531,44096:29688,44097:29689,44098:29690,44099:29691,44100:29692,44101:29693,44102:29694,44103:29695,44104:29696,44105:29697,44106:29698,44107:29700,44108:29703,44109:29704,44110:29707,44111:29708,44112:29709,44113:29710,44114:29713,44115:29714,44116:29715,44117:29716,44118:29717,44119:29718,44120:29719,44121:29720,44122:29721,44123:29724,44124:29725,44125:29726,44126:29727,44127:29728,44128:29729,44129:29731,44130:29732,44131:29735,44132:29737,44133:29739,44134:29741,44135:29743,44136:29745,44137:29746,44138:29751,44139:29752,44140:29753,44141:29754,44142:29755,44143:29757,44144:29758,44145:29759,44146:29760,44147:29762,44148:29763,44149:29764,44150:29765,44151:29766,44152:29767,44153:29768,44154:29769,44155:29770,44156:29771,44157:29772,44158:29773,44160:29774,44161:29775,44162:29776,44163:29777,44164:29778,44165:29779,44166:29780,44167:29782,44168:29784,44169:29789,44170:29792,44171:29793,44172:29794,44173:29795,44174:29796,44175:29797,44176:29798,44177:29799,44178:29800,44179:29801,44180:29802,44181:29803,44182:29804,44183:29806,44184:29807,44185:29809,44186:29810,44187:29811,44188:29812,44189:29813,44190:29816,44191:29817,44192:29818,44193:57532,44194:57533,44195:57534,44196:57535,44197:57536,44198:57537,44199:57538,44200:57539,44201:57540,44202:57541,44203:57542,44204:57543,44205:57544,44206:57545,44207:57546,44208:57547,44209:57548,44210:57549,44211:57550,44212:57551,44213:57552,44214:57553,44215:57554,44216:57555,44217:57556,44218:57557,44219:57558,44220:57559,44221:57560,44222:57561,44223:57562,44224:57563,44225:57564,44226:57565,44227:57566,44228:57567,44229:57568,44230:57569,44231:57570,44232:57571,44233:57572,44234:57573,44235:57574,44236:57575,44237:57576,44238:57577,44239:57578,44240:57579,44241:57580,44242:57581,44243:57582,44244:57583,44245:57584,44246:57585,44247:57586,44248:57587,44249:57588,44250:57589,44251:57590,44252:57591,44253:57592,44254:57593,44255:57594,44256:57595,44257:57596,44258:57597,44259:57598,44260:57599,44261:57600,44262:57601,44263:57602,44264:57603,44265:57604,44266:57605,44267:57606,44268:57607,44269:57608,44270:57609,44271:57610,44272:57611,44273:57612,44274:57613,44275:57614,44276:57615,44277:57616,44278:57617,44279:57618,44280:57619,44281:57620,44282:57621,44283:57622,44284:57623,44285:57624,44286:57625,44352:29819,44353:29820,44354:29821,44355:29823,44356:29826,44357:29828,44358:29829,44359:29830,44360:29832,44361:29833,44362:29834,44363:29836,44364:29837,44365:29839,44366:29841,44367:29842,44368:29843,44369:29844,44370:29845,44371:29846,44372:29847,44373:29848,44374:29849,44375:29850,44376:29851,44377:29853,44378:29855,44379:29856,44380:29857,44381:29858,44382:29859,44383:29860,44384:29861,44385:29862,44386:29866,44387:29867,44388:29868,44389:29869,44390:29870,44391:29871,44392:29872,44393:29873,44394:29874,44395:29875,44396:29876,44397:29877,44398:29878,44399:29879,44400:29880,44401:29881,44402:29883,44403:29884,44404:29885,44405:29886,44406:29887,44407:29888,44408:29889,44409:29890,44410:29891,44411:29892,44412:29893,44413:29894,44414:29895,44416:29896,44417:29897,44418:29898,44419:29899,44420:29900,44421:29901,44422:29902,44423:29903,44424:29904,44425:29905,44426:29907,44427:29908,44428:29909,44429:29910,44430:29911,44431:29912,44432:29913,44433:29914,44434:29915,44435:29917,44436:29919,44437:29921,44438:29925,44439:29927,44440:29928,44441:29929,44442:29930,44443:29931,44444:29932,44445:29933,44446:29936,44447:29937,44448:29938,44449:57626,44450:57627,44451:57628,44452:57629,44453:57630,44454:57631,44455:57632,44456:57633,44457:57634,44458:57635,44459:57636,44460:57637,44461:57638,44462:57639,44463:57640,44464:57641,44465:57642,44466:57643,44467:57644,44468:57645,44469:57646,44470:57647,44471:57648,44472:57649,44473:57650,44474:57651,44475:57652,44476:57653,44477:57654,44478:57655,44479:57656,44480:57657,44481:57658,44482:57659,44483:57660,44484:57661,44485:57662,44486:57663,44487:57664,44488:57665,44489:57666,44490:57667,44491:57668,44492:57669,44493:57670,44494:57671,44495:57672,44496:57673,44497:57674,44498:57675,44499:57676,44500:57677,44501:57678,44502:57679,44503:57680,44504:57681,44505:57682,44506:57683,44507:57684,44508:57685,44509:57686,44510:57687,44511:57688,44512:57689,44513:57690,44514:57691,44515:57692,44516:57693,44517:57694,44518:57695,44519:57696,44520:57697,44521:57698,44522:57699,44523:57700,44524:57701,44525:57702,44526:57703,44527:57704,44528:57705,44529:57706,44530:57707,44531:57708,44532:57709,44533:57710,44534:57711,44535:57712,44536:57713,44537:57714,44538:57715,44539:57716,44540:57717,44541:57718,44542:57719,44608:29939,44609:29941,44610:29944,44611:29945,44612:29946,44613:29947,44614:29948,44615:29949,44616:29950,44617:29952,44618:29953,44619:29954,44620:29955,44621:29957,44622:29958,44623:29959,44624:29960,44625:29961,44626:29962,44627:29963,44628:29964,44629:29966,44630:29968,44631:29970,44632:29972,44633:29973,44634:29974,44635:29975,44636:29979,44637:29981,44638:29982,44639:29984,44640:29985,44641:29986,44642:29987,44643:29988,44644:29990,44645:29991,44646:29994,44647:29998,44648:30004,44649:30006,44650:30009,44651:30012,44652:30013,44653:30015,44654:30017,44655:30018,44656:30019,44657:30020,44658:30022,44659:30023,44660:30025,44661:30026,44662:30029,44663:30032,44664:30033,44665:30034,44666:30035,44667:30037,44668:30038,44669:30039,44670:30040,44672:30045,44673:30046,44674:30047,44675:30048,44676:30049,44677:30050,44678:30051,44679:30052,44680:30055,44681:30056,44682:30057,44683:30059,44684:30060,44685:30061,44686:30062,44687:30063,44688:30064,44689:30065,44690:30067,44691:30069,44692:30070,44693:30071,44694:30074,44695:30075,44696:30076,44697:30077,44698:30078,44699:30080,44700:30081,44701:30082,44702:30084,44703:30085,44704:30087,44705:57720,44706:57721,44707:57722,44708:57723,44709:57724,44710:57725,44711:57726,44712:57727,44713:57728,44714:57729,44715:57730,44716:57731,44717:57732,44718:57733,44719:57734,44720:57735,44721:57736,44722:57737,44723:57738,44724:57739,44725:57740,44726:57741,44727:57742,44728:57743,44729:57744,44730:57745,44731:57746,44732:57747,44733:57748,44734:57749,44735:57750,44736:57751,44737:57752,44738:57753,44739:57754,44740:57755,44741:57756,44742:57757,44743:57758,44744:57759,44745:57760,44746:57761,44747:57762,44748:57763,44749:57764,44750:57765,44751:57766,44752:57767,44753:57768,44754:57769,44755:57770,44756:57771,44757:57772,44758:57773,44759:57774,44760:57775,44761:57776,44762:57777,44763:57778,44764:57779,44765:57780,44766:57781,44767:57782,44768:57783,44769:57784,44770:57785,44771:57786,44772:57787,44773:57788,44774:57789,44775:57790,44776:57791,44777:57792,44778:57793,44779:57794,44780:57795,44781:57796,44782:57797,44783:57798,44784:57799,44785:57800,44786:57801,44787:57802,44788:57803,44789:57804,44790:57805,44791:57806,44792:57807,44793:57808,44794:57809,44795:57810,44796:57811,44797:57812,44798:57813,44864:30088,44865:30089,44866:30090,44867:30092,44868:30093,44869:30094,44870:30096,44871:30099,44872:30101,44873:30104,44874:30107,44875:30108,44876:30110,44877:30114,44878:30118,44879:30119,44880:30120,44881:30121,44882:30122,44883:30125,44884:30134,44885:30135,44886:30138,44887:30139,44888:30143,44889:30144,44890:30145,44891:30150,44892:30155,44893:30156,44894:30158,44895:30159,44896:30160,44897:30161,44898:30163,44899:30167,44900:30169,44901:30170,44902:30172,44903:30173,44904:30175,44905:30176,44906:30177,44907:30181,44908:30185,44909:30188,44910:30189,44911:30190,44912:30191,44913:30194,44914:30195,44915:30197,44916:30198,44917:30199,44918:30200,44919:30202,44920:30203,44921:30205,44922:30206,44923:30210,44924:30212,44925:30214,44926:30215,44928:30216,44929:30217,44930:30219,44931:30221,44932:30222,44933:30223,44934:30225,44935:30226,44936:30227,44937:30228,44938:30230,44939:30234,44940:30236,44941:30237,44942:30238,44943:30241,44944:30243,44945:30247,44946:30248,44947:30252,44948:30254,44949:30255,44950:30257,44951:30258,44952:30262,44953:30263,44954:30265,44955:30266,44956:30267,44957:30269,44958:30273,44959:30274,44960:30276,44961:57814,44962:57815,44963:57816,44964:57817,44965:57818,44966:57819,44967:57820,44968:57821,44969:57822,44970:57823,44971:57824,44972:57825,44973:57826,44974:57827,44975:57828,44976:57829,44977:57830,44978:57831,44979:57832,44980:57833,44981:57834,44982:57835,44983:57836,44984:57837,44985:57838,44986:57839,44987:57840,44988:57841,44989:57842,44990:57843,44991:57844,44992:57845,44993:57846,44994:57847,44995:57848,44996:57849,44997:57850,44998:57851,44999:57852,45000:57853,45001:57854,45002:57855,45003:57856,45004:57857,45005:57858,45006:57859,45007:57860,45008:57861,45009:57862,45010:57863,45011:57864,45012:57865,45013:57866,45014:57867,45015:57868,45016:57869,45017:57870,45018:57871,45019:57872,45020:57873,45021:57874,45022:57875,45023:57876,45024:57877,45025:57878,45026:57879,45027:57880,45028:57881,45029:57882,45030:57883,45031:57884,45032:57885,45033:57886,45034:57887,45035:57888,45036:57889,45037:57890,45038:57891,45039:57892,45040:57893,45041:57894,45042:57895,45043:57896,45044:57897,45045:57898,45046:57899,45047:57900,45048:57901,45049:57902,45050:57903,45051:57904,45052:57905,45053:57906,45054:57907,45120:30277,45121:30278,45122:30279,45123:30280,45124:30281,45125:30282,45126:30283,45127:30286,45128:30287,45129:30288,45130:30289,45131:30290,45132:30291,45133:30293,45134:30295,45135:30296,45136:30297,45137:30298,45138:30299,45139:30301,45140:30303,45141:30304,45142:30305,45143:30306,45144:30308,45145:30309,45146:30310,45147:30311,45148:30312,45149:30313,45150:30314,45151:30316,45152:30317,45153:30318,45154:30320,45155:30321,45156:30322,45157:30323,45158:30324,45159:30325,45160:30326,45161:30327,45162:30329,45163:30330,45164:30332,45165:30335,45166:30336,45167:30337,45168:30339,45169:30341,45170:30345,45171:30346,45172:30348,45173:30349,45174:30351,45175:30352,45176:30354,45177:30356,45178:30357,45179:30359,45180:30360,45181:30362,45182:30363,45184:30364,45185:30365,45186:30366,45187:30367,45188:30368,45189:30369,45190:30370,45191:30371,45192:30373,45193:30374,45194:30375,45195:30376,45196:30377,45197:30378,45198:30379,45199:30380,45200:30381,45201:30383,45202:30384,45203:30387,45204:30389,45205:30390,45206:30391,45207:30392,45208:30393,45209:30394,45210:30395,45211:30396,45212:30397,45213:30398,45214:30400,45215:30401,45216:30403,45217:21834,45218:38463,45219:22467,45220:25384,45221:21710,45222:21769,45223:21696,45224:30353,45225:30284,45226:34108,45227:30702,45228:33406,45229:30861,45230:29233,45231:38552,45232:38797,45233:27688,45234:23433,45235:20474,45236:25353,45237:26263,45238:23736,45239:33018,45240:26696,45241:32942,45242:26114,45243:30414,45244:20985,45245:25942,45246:29100,45247:32753,45248:34948,45249:20658,45250:22885,45251:25034,45252:28595,45253:33453,45254:25420,45255:25170,45256:21485,45257:21543,45258:31494,45259:20843,45260:30116,45261:24052,45262:25300,45263:36299,45264:38774,45265:25226,45266:32793,45267:22365,45268:38712,45269:32610,45270:29240,45271:30333,45272:26575,45273:30334,45274:25670,45275:20336,45276:36133,45277:25308,45278:31255,45279:26001,45280:29677,45281:25644,45282:25203,45283:33324,45284:39041,45285:26495,45286:29256,45287:25198,45288:25292,45289:20276,45290:29923,45291:21322,45292:21150,45293:32458,45294:37030,45295:24110,45296:26758,45297:27036,45298:33152,45299:32465,45300:26834,45301:30917,45302:34444,45303:38225,45304:20621,45305:35876,45306:33502,45307:32990,45308:21253,45309:35090,45310:21093,45376:30404,45377:30407,45378:30409,45379:30411,45380:30412,45381:30419,45382:30421,45383:30425,45384:30426,45385:30428,45386:30429,45387:30430,45388:30432,45389:30433,45390:30434,45391:30435,45392:30436,45393:30438,45394:30439,45395:30440,45396:30441,45397:30442,45398:30443,45399:30444,45400:30445,45401:30448,45402:30451,45403:30453,45404:30454,45405:30455,45406:30458,45407:30459,45408:30461,45409:30463,45410:30464,45411:30466,45412:30467,45413:30469,45414:30470,45415:30474,45416:30476,45417:30478,45418:30479,45419:30480,45420:30481,45421:30482,45422:30483,45423:30484,45424:30485,45425:30486,45426:30487,45427:30488,45428:30491,45429:30492,45430:30493,45431:30494,45432:30497,45433:30499,45434:30500,45435:30501,45436:30503,45437:30506,45438:30507,45440:30508,45441:30510,45442:30512,45443:30513,45444:30514,45445:30515,45446:30516,45447:30521,45448:30523,45449:30525,45450:30526,45451:30527,45452:30530,45453:30532,45454:30533,45455:30534,45456:30536,45457:30537,45458:30538,45459:30539,45460:30540,45461:30541,45462:30542,45463:30543,45464:30546,45465:30547,45466:30548,45467:30549,45468:30550,45469:30551,45470:30552,45471:30553,45472:30556,45473:34180,45474:38649,45475:20445,45476:22561,45477:39281,45478:23453,45479:25265,45480:25253,45481:26292,45482:35961,45483:40077,45484:29190,45485:26479,45486:30865,45487:24754,45488:21329,45489:21271,45490:36744,45491:32972,45492:36125,45493:38049,45494:20493,45495:29384,45496:22791,45497:24811,45498:28953,45499:34987,45500:22868,45501:33519,45502:26412,45503:31528,45504:23849,45505:32503,45506:29997,45507:27893,45508:36454,45509:36856,45510:36924,45511:40763,45512:27604,45513:37145,45514:31508,45515:24444,45516:30887,45517:34006,45518:34109,45519:27605,45520:27609,45521:27606,45522:24065,45523:24199,45524:30201,45525:38381,45526:25949,45527:24330,45528:24517,45529:36767,45530:22721,45531:33218,45532:36991,45533:38491,45534:38829,45535:36793,45536:32534,45537:36140,45538:25153,45539:20415,45540:21464,45541:21342,45542:36776,45543:36777,45544:36779,45545:36941,45546:26631,45547:24426,45548:33176,45549:34920,45550:40150,45551:24971,45552:21035,45553:30250,45554:24428,45555:25996,45556:28626,45557:28392,45558:23486,45559:25672,45560:20853,45561:20912,45562:26564,45563:19993,45564:31177,45565:39292,45566:28851,45632:30557,45633:30558,45634:30559,45635:30560,45636:30564,45637:30567,45638:30569,45639:30570,45640:30573,45641:30574,45642:30575,45643:30576,45644:30577,45645:30578,45646:30579,45647:30580,45648:30581,45649:30582,45650:30583,45651:30584,45652:30586,45653:30587,45654:30588,45655:30593,45656:30594,45657:30595,45658:30598,45659:30599,45660:30600,45661:30601,45662:30602,45663:30603,45664:30607,45665:30608,45666:30611,45667:30612,45668:30613,45669:30614,45670:30615,45671:30616,45672:30617,45673:30618,45674:30619,45675:30620,45676:30621,45677:30622,45678:30625,45679:30627,45680:30628,45681:30630,45682:30632,45683:30635,45684:30637,45685:30638,45686:30639,45687:30641,45688:30642,45689:30644,45690:30646,45691:30647,45692:30648,45693:30649,45694:30650,45696:30652,45697:30654,45698:30656,45699:30657,45700:30658,45701:30659,45702:30660,45703:30661,45704:30662,45705:30663,45706:30664,45707:30665,45708:30666,45709:30667,45710:30668,45711:30670,45712:30671,45713:30672,45714:30673,45715:30674,45716:30675,45717:30676,45718:30677,45719:30678,45720:30680,45721:30681,45722:30682,45723:30685,45724:30686,45725:30687,45726:30688,45727:30689,45728:30692,45729:30149,45730:24182,45731:29627,45732:33760,45733:25773,45734:25320,45735:38069,45736:27874,45737:21338,45738:21187,45739:25615,45740:38082,45741:31636,45742:20271,45743:24091,45744:33334,45745:33046,45746:33162,45747:28196,45748:27850,45749:39539,45750:25429,45751:21340,45752:21754,45753:34917,45754:22496,45755:19981,45756:24067,45757:27493,45758:31807,45759:37096,45760:24598,45761:25830,45762:29468,45763:35009,45764:26448,45765:25165,45766:36130,45767:30572,45768:36393,45769:37319,45770:24425,45771:33756,45772:34081,45773:39184,45774:21442,45775:34453,45776:27531,45777:24813,45778:24808,45779:28799,45780:33485,45781:33329,45782:20179,45783:27815,45784:34255,45785:25805,45786:31961,45787:27133,45788:26361,45789:33609,45790:21397,45791:31574,45792:20391,45793:20876,45794:27979,45795:23618,45796:36461,45797:25554,45798:21449,45799:33580,45800:33590,45801:26597,45802:30900,45803:25661,45804:23519,45805:23700,45806:24046,45807:35815,45808:25286,45809:26612,45810:35962,45811:25600,45812:25530,45813:34633,45814:39307,45815:35863,45816:32544,45817:38130,45818:20135,45819:38416,45820:39076,45821:26124,45822:29462,45888:30694,45889:30696,45890:30698,45891:30703,45892:30704,45893:30705,45894:30706,45895:30708,45896:30709,45897:30711,45898:30713,45899:30714,45900:30715,45901:30716,45902:30723,45903:30724,45904:30725,45905:30726,45906:30727,45907:30728,45908:30730,45909:30731,45910:30734,45911:30735,45912:30736,45913:30739,45914:30741,45915:30745,45916:30747,45917:30750,45918:30752,45919:30753,45920:30754,45921:30756,45922:30760,45923:30762,45924:30763,45925:30766,45926:30767,45927:30769,45928:30770,45929:30771,45930:30773,45931:30774,45932:30781,45933:30783,45934:30785,45935:30786,45936:30787,45937:30788,45938:30790,45939:30792,45940:30793,45941:30794,45942:30795,45943:30797,45944:30799,45945:30801,45946:30803,45947:30804,45948:30808,45949:30809,45950:30810,45952:30811,45953:30812,45954:30814,45955:30815,45956:30816,45957:30817,45958:30818,45959:30819,45960:30820,45961:30821,45962:30822,45963:30823,45964:30824,45965:30825,45966:30831,45967:30832,45968:30833,45969:30834,45970:30835,45971:30836,45972:30837,45973:30838,45974:30840,45975:30841,45976:30842,45977:30843,45978:30845,45979:30846,45980:30847,45981:30848,45982:30849,45983:30850,45984:30851,45985:22330,45986:23581,45987:24120,45988:38271,45989:20607,45990:32928,45991:21378,45992:25950,45993:30021,45994:21809,45995:20513,45996:36229,45997:25220,45998:38046,45999:26397,46000:22066,46001:28526,46002:24034,46003:21557,46004:28818,46005:36710,46006:25199,46007:25764,46008:25507,46009:24443,46010:28552,46011:37108,46012:33251,46013:36784,46014:23576,46015:26216,46016:24561,46017:27785,46018:38472,46019:36225,46020:34924,46021:25745,46022:31216,46023:22478,46024:27225,46025:25104,46026:21576,46027:20056,46028:31243,46029:24809,46030:28548,46031:35802,46032:25215,46033:36894,46034:39563,46035:31204,46036:21507,46037:30196,46038:25345,46039:21273,46040:27744,46041:36831,46042:24347,46043:39536,46044:32827,46045:40831,46046:20360,46047:23610,46048:36196,46049:32709,46050:26021,46051:28861,46052:20805,46053:20914,46054:34411,46055:23815,46056:23456,46057:25277,46058:37228,46059:30068,46060:36364,46061:31264,46062:24833,46063:31609,46064:20167,46065:32504,46066:30597,46067:19985,46068:33261,46069:21021,46070:20986,46071:27249,46072:21416,46073:36487,46074:38148,46075:38607,46076:28353,46077:38500,46078:26970,46144:30852,46145:30853,46146:30854,46147:30856,46148:30858,46149:30859,46150:30863,46151:30864,46152:30866,46153:30868,46154:30869,46155:30870,46156:30873,46157:30877,46158:30878,46159:30880,46160:30882,46161:30884,46162:30886,46163:30888,46164:30889,46165:30890,46166:30891,46167:30892,46168:30893,46169:30894,46170:30895,46171:30901,46172:30902,46173:30903,46174:30904,46175:30906,46176:30907,46177:30908,46178:30909,46179:30911,46180:30912,46181:30914,46182:30915,46183:30916,46184:30918,46185:30919,46186:30920,46187:30924,46188:30925,46189:30926,46190:30927,46191:30929,46192:30930,46193:30931,46194:30934,46195:30935,46196:30936,46197:30938,46198:30939,46199:30940,46200:30941,46201:30942,46202:30943,46203:30944,46204:30945,46205:30946,46206:30947,46208:30948,46209:30949,46210:30950,46211:30951,46212:30953,46213:30954,46214:30955,46215:30957,46216:30958,46217:30959,46218:30960,46219:30961,46220:30963,46221:30965,46222:30966,46223:30968,46224:30969,46225:30971,46226:30972,46227:30973,46228:30974,46229:30975,46230:30976,46231:30978,46232:30979,46233:30980,46234:30982,46235:30983,46236:30984,46237:30985,46238:30986,46239:30987,46240:30988,46241:30784,46242:20648,46243:30679,46244:25616,46245:35302,46246:22788,46247:25571,46248:24029,46249:31359,46250:26941,46251:20256,46252:33337,46253:21912,46254:20018,46255:30126,46256:31383,46257:24162,46258:24202,46259:38383,46260:21019,46261:21561,46262:28810,46263:25462,46264:38180,46265:22402,46266:26149,46267:26943,46268:37255,46269:21767,46270:28147,46271:32431,46272:34850,46273:25139,46274:32496,46275:30133,46276:33576,46277:30913,46278:38604,46279:36766,46280:24904,46281:29943,46282:35789,46283:27492,46284:21050,46285:36176,46286:27425,46287:32874,46288:33905,46289:22257,46290:21254,46291:20174,46292:19995,46293:20945,46294:31895,46295:37259,46296:31751,46297:20419,46298:36479,46299:31713,46300:31388,46301:25703,46302:23828,46303:20652,46304:33030,46305:30209,46306:31929,46307:28140,46308:32736,46309:26449,46310:23384,46311:23544,46312:30923,46313:25774,46314:25619,46315:25514,46316:25387,46317:38169,46318:25645,46319:36798,46320:31572,46321:30249,46322:25171,46323:22823,46324:21574,46325:27513,46326:20643,46327:25140,46328:24102,46329:27526,46330:20195,46331:36151,46332:34955,46333:24453,46334:36910,46400:30989,46401:30990,46402:30991,46403:30992,46404:30993,46405:30994,46406:30996,46407:30997,46408:30998,46409:30999,46410:31000,46411:31001,46412:31002,46413:31003,46414:31004,46415:31005,46416:31007,46417:31008,46418:31009,46419:31010,46420:31011,46421:31013,46422:31014,46423:31015,46424:31016,46425:31017,46426:31018,46427:31019,46428:31020,46429:31021,46430:31022,46431:31023,46432:31024,46433:31025,46434:31026,46435:31027,46436:31029,46437:31030,46438:31031,46439:31032,46440:31033,46441:31037,46442:31039,46443:31042,46444:31043,46445:31044,46446:31045,46447:31047,46448:31050,46449:31051,46450:31052,46451:31053,46452:31054,46453:31055,46454:31056,46455:31057,46456:31058,46457:31060,46458:31061,46459:31064,46460:31065,46461:31073,46462:31075,46464:31076,46465:31078,46466:31081,46467:31082,46468:31083,46469:31084,46470:31086,46471:31088,46472:31089,46473:31090,46474:31091,46475:31092,46476:31093,46477:31094,46478:31097,46479:31099,46480:31100,46481:31101,46482:31102,46483:31103,46484:31106,46485:31107,46486:31110,46487:31111,46488:31112,46489:31113,46490:31115,46491:31116,46492:31117,46493:31118,46494:31120,46495:31121,46496:31122,46497:24608,46498:32829,46499:25285,46500:20025,46501:21333,46502:37112,46503:25528,46504:32966,46505:26086,46506:27694,46507:20294,46508:24814,46509:28129,46510:35806,46511:24377,46512:34507,46513:24403,46514:25377,46515:20826,46516:33633,46517:26723,46518:20992,46519:25443,46520:36424,46521:20498,46522:23707,46523:31095,46524:23548,46525:21040,46526:31291,46527:24764,46528:36947,46529:30423,46530:24503,46531:24471,46532:30340,46533:36460,46534:28783,46535:30331,46536:31561,46537:30634,46538:20979,46539:37011,46540:22564,46541:20302,46542:28404,46543:36842,46544:25932,46545:31515,46546:29380,46547:28068,46548:32735,46549:23265,46550:25269,46551:24213,46552:22320,46553:33922,46554:31532,46555:24093,46556:24351,46557:36882,46558:32532,46559:39072,46560:25474,46561:28359,46562:30872,46563:28857,46564:20856,46565:38747,46566:22443,46567:30005,46568:20291,46569:30008,46570:24215,46571:24806,46572:22880,46573:28096,46574:27583,46575:30857,46576:21500,46577:38613,46578:20939,46579:20993,46580:25481,46581:21514,46582:38035,46583:35843,46584:36300,46585:29241,46586:30879,46587:34678,46588:36845,46589:35853,46590:21472,46656:31123,46657:31124,46658:31125,46659:31126,46660:31127,46661:31128,46662:31129,46663:31131,46664:31132,46665:31133,46666:31134,46667:31135,46668:31136,46669:31137,46670:31138,46671:31139,46672:31140,46673:31141,46674:31142,46675:31144,46676:31145,46677:31146,46678:31147,46679:31148,46680:31149,46681:31150,46682:31151,46683:31152,46684:31153,46685:31154,46686:31156,46687:31157,46688:31158,46689:31159,46690:31160,46691:31164,46692:31167,46693:31170,46694:31172,46695:31173,46696:31175,46697:31176,46698:31178,46699:31180,46700:31182,46701:31183,46702:31184,46703:31187,46704:31188,46705:31190,46706:31191,46707:31193,46708:31194,46709:31195,46710:31196,46711:31197,46712:31198,46713:31200,46714:31201,46715:31202,46716:31205,46717:31208,46718:31210,46720:31212,46721:31214,46722:31217,46723:31218,46724:31219,46725:31220,46726:31221,46727:31222,46728:31223,46729:31225,46730:31226,46731:31228,46732:31230,46733:31231,46734:31233,46735:31236,46736:31237,46737:31239,46738:31240,46739:31241,46740:31242,46741:31244,46742:31247,46743:31248,46744:31249,46745:31250,46746:31251,46747:31253,46748:31254,46749:31256,46750:31257,46751:31259,46752:31260,46753:19969,46754:30447,46755:21486,46756:38025,46757:39030,46758:40718,46759:38189,46760:23450,46761:35746,46762:20002,46763:19996,46764:20908,46765:33891,46766:25026,46767:21160,46768:26635,46769:20375,46770:24683,46771:20923,46772:27934,46773:20828,46774:25238,46775:26007,46776:38497,46777:35910,46778:36887,46779:30168,46780:37117,46781:30563,46782:27602,46783:29322,46784:29420,46785:35835,46786:22581,46787:30585,46788:36172,46789:26460,46790:38208,46791:32922,46792:24230,46793:28193,46794:22930,46795:31471,46796:30701,46797:38203,46798:27573,46799:26029,46800:32526,46801:22534,46802:20817,46803:38431,46804:23545,46805:22697,46806:21544,46807:36466,46808:25958,46809:39039,46810:22244,46811:38045,46812:30462,46813:36929,46814:25479,46815:21702,46816:22810,46817:22842,46818:22427,46819:36530,46820:26421,46821:36346,46822:33333,46823:21057,46824:24816,46825:22549,46826:34558,46827:23784,46828:40517,46829:20420,46830:39069,46831:35769,46832:23077,46833:24694,46834:21380,46835:25212,46836:36943,46837:37122,46838:39295,46839:24681,46840:32780,46841:20799,46842:32819,46843:23572,46844:39285,46845:27953,46846:20108,46912:31261,46913:31263,46914:31265,46915:31266,46916:31268,46917:31269,46918:31270,46919:31271,46920:31272,46921:31273,46922:31274,46923:31275,46924:31276,46925:31277,46926:31278,46927:31279,46928:31280,46929:31281,46930:31282,46931:31284,46932:31285,46933:31286,46934:31288,46935:31290,46936:31294,46937:31296,46938:31297,46939:31298,46940:31299,46941:31300,46942:31301,46943:31303,46944:31304,46945:31305,46946:31306,46947:31307,46948:31308,46949:31309,46950:31310,46951:31311,46952:31312,46953:31314,46954:31315,46955:31316,46956:31317,46957:31318,46958:31320,46959:31321,46960:31322,46961:31323,46962:31324,46963:31325,46964:31326,46965:31327,46966:31328,46967:31329,46968:31330,46969:31331,46970:31332,46971:31333,46972:31334,46973:31335,46974:31336,46976:31337,46977:31338,46978:31339,46979:31340,46980:31341,46981:31342,46982:31343,46983:31345,46984:31346,46985:31347,46986:31349,46987:31355,46988:31356,46989:31357,46990:31358,46991:31362,46992:31365,46993:31367,46994:31369,46995:31370,46996:31371,46997:31372,46998:31374,46999:31375,47000:31376,47001:31379,47002:31380,47003:31385,47004:31386,47005:31387,47006:31390,47007:31393,47008:31394,47009:36144,47010:21457,47011:32602,47012:31567,47013:20240,47014:20047,47015:38400,47016:27861,47017:29648,47018:34281,47019:24070,47020:30058,47021:32763,47022:27146,47023:30718,47024:38034,47025:32321,47026:20961,47027:28902,47028:21453,47029:36820,47030:33539,47031:36137,47032:29359,47033:39277,47034:27867,47035:22346,47036:33459,47037:26041,47038:32938,47039:25151,47040:38450,47041:22952,47042:20223,47043:35775,47044:32442,47045:25918,47046:33778,47047:38750,47048:21857,47049:39134,47050:32933,47051:21290,47052:35837,47053:21536,47054:32954,47055:24223,47056:27832,47057:36153,47058:33452,47059:37210,47060:21545,47061:27675,47062:20998,47063:32439,47064:22367,47065:28954,47066:27774,47067:31881,47068:22859,47069:20221,47070:24575,47071:24868,47072:31914,47073:20016,47074:23553,47075:26539,47076:34562,47077:23792,47078:38155,47079:39118,47080:30127,47081:28925,47082:36898,47083:20911,47084:32541,47085:35773,47086:22857,47087:20964,47088:20315,47089:21542,47090:22827,47091:25975,47092:32932,47093:23413,47094:25206,47095:25282,47096:36752,47097:24133,47098:27679,47099:31526,47100:20239,47101:20440,47102:26381,47168:31395,47169:31396,47170:31399,47171:31401,47172:31402,47173:31403,47174:31406,47175:31407,47176:31408,47177:31409,47178:31410,47179:31412,47180:31413,47181:31414,47182:31415,47183:31416,47184:31417,47185:31418,47186:31419,47187:31420,47188:31421,47189:31422,47190:31424,47191:31425,47192:31426,47193:31427,47194:31428,47195:31429,47196:31430,47197:31431,47198:31432,47199:31433,47200:31434,47201:31436,47202:31437,47203:31438,47204:31439,47205:31440,47206:31441,47207:31442,47208:31443,47209:31444,47210:31445,47211:31447,47212:31448,47213:31450,47214:31451,47215:31452,47216:31453,47217:31457,47218:31458,47219:31460,47220:31463,47221:31464,47222:31465,47223:31466,47224:31467,47225:31468,47226:31470,47227:31472,47228:31473,47229:31474,47230:31475,47232:31476,47233:31477,47234:31478,47235:31479,47236:31480,47237:31483,47238:31484,47239:31486,47240:31488,47241:31489,47242:31490,47243:31493,47244:31495,47245:31497,47246:31500,47247:31501,47248:31502,47249:31504,47250:31506,47251:31507,47252:31510,47253:31511,47254:31512,47255:31514,47256:31516,47257:31517,47258:31519,47259:31521,47260:31522,47261:31523,47262:31527,47263:31529,47264:31533,47265:28014,47266:28074,47267:31119,47268:34993,47269:24343,47270:29995,47271:25242,47272:36741,47273:20463,47274:37340,47275:26023,47276:33071,47277:33105,47278:24220,47279:33104,47280:36212,47281:21103,47282:35206,47283:36171,47284:22797,47285:20613,47286:20184,47287:38428,47288:29238,47289:33145,47290:36127,47291:23500,47292:35747,47293:38468,47294:22919,47295:32538,47296:21648,47297:22134,47298:22030,47299:35813,47300:25913,47301:27010,47302:38041,47303:30422,47304:28297,47305:24178,47306:29976,47307:26438,47308:26577,47309:31487,47310:32925,47311:36214,47312:24863,47313:31174,47314:25954,47315:36195,47316:20872,47317:21018,47318:38050,47319:32568,47320:32923,47321:32434,47322:23703,47323:28207,47324:26464,47325:31705,47326:30347,47327:39640,47328:33167,47329:32660,47330:31957,47331:25630,47332:38224,47333:31295,47334:21578,47335:21733,47336:27468,47337:25601,47338:25096,47339:40509,47340:33011,47341:30105,47342:21106,47343:38761,47344:33883,47345:26684,47346:34532,47347:38401,47348:38548,47349:38124,47350:20010,47351:21508,47352:32473,47353:26681,47354:36319,47355:32789,47356:26356,47357:24218,47358:32697,47424:31535,47425:31536,47426:31538,47427:31540,47428:31541,47429:31542,47430:31543,47431:31545,47432:31547,47433:31549,47434:31551,47435:31552,47436:31553,47437:31554,47438:31555,47439:31556,47440:31558,47441:31560,47442:31562,47443:31565,47444:31566,47445:31571,47446:31573,47447:31575,47448:31577,47449:31580,47450:31582,47451:31583,47452:31585,47453:31587,47454:31588,47455:31589,47456:31590,47457:31591,47458:31592,47459:31593,47460:31594,47461:31595,47462:31596,47463:31597,47464:31599,47465:31600,47466:31603,47467:31604,47468:31606,47469:31608,47470:31610,47471:31612,47472:31613,47473:31615,47474:31617,47475:31618,47476:31619,47477:31620,47478:31622,47479:31623,47480:31624,47481:31625,47482:31626,47483:31627,47484:31628,47485:31630,47486:31631,47488:31633,47489:31634,47490:31635,47491:31638,47492:31640,47493:31641,47494:31642,47495:31643,47496:31646,47497:31647,47498:31648,47499:31651,47500:31652,47501:31653,47502:31662,47503:31663,47504:31664,47505:31666,47506:31667,47507:31669,47508:31670,47509:31671,47510:31673,47511:31674,47512:31675,47513:31676,47514:31677,47515:31678,47516:31679,47517:31680,47518:31682,47519:31683,47520:31684,47521:22466,47522:32831,47523:26775,47524:24037,47525:25915,47526:21151,47527:24685,47528:40858,47529:20379,47530:36524,47531:20844,47532:23467,47533:24339,47534:24041,47535:27742,47536:25329,47537:36129,47538:20849,47539:38057,47540:21246,47541:27807,47542:33503,47543:29399,47544:22434,47545:26500,47546:36141,47547:22815,47548:36764,47549:33735,47550:21653,47551:31629,47552:20272,47553:27837,47554:23396,47555:22993,47556:40723,47557:21476,47558:34506,47559:39592,47560:35895,47561:32929,47562:25925,47563:39038,47564:22266,47565:38599,47566:21038,47567:29916,47568:21072,47569:23521,47570:25346,47571:35074,47572:20054,47573:25296,47574:24618,47575:26874,47576:20851,47577:23448,47578:20896,47579:35266,47580:31649,47581:39302,47582:32592,47583:24815,47584:28748,47585:36143,47586:20809,47587:24191,47588:36891,47589:29808,47590:35268,47591:22317,47592:30789,47593:24402,47594:40863,47595:38394,47596:36712,47597:39740,47598:35809,47599:30328,47600:26690,47601:26588,47602:36330,47603:36149,47604:21053,47605:36746,47606:28378,47607:26829,47608:38149,47609:37101,47610:22269,47611:26524,47612:35065,47613:36807,47614:21704,47680:31685,47681:31688,47682:31689,47683:31690,47684:31691,47685:31693,47686:31694,47687:31695,47688:31696,47689:31698,47690:31700,47691:31701,47692:31702,47693:31703,47694:31704,47695:31707,47696:31708,47697:31710,47698:31711,47699:31712,47700:31714,47701:31715,47702:31716,47703:31719,47704:31720,47705:31721,47706:31723,47707:31724,47708:31725,47709:31727,47710:31728,47711:31730,47712:31731,47713:31732,47714:31733,47715:31734,47716:31736,47717:31737,47718:31738,47719:31739,47720:31741,47721:31743,47722:31744,47723:31745,47724:31746,47725:31747,47726:31748,47727:31749,47728:31750,47729:31752,47730:31753,47731:31754,47732:31757,47733:31758,47734:31760,47735:31761,47736:31762,47737:31763,47738:31764,47739:31765,47740:31767,47741:31768,47742:31769,47744:31770,47745:31771,47746:31772,47747:31773,47748:31774,47749:31776,47750:31777,47751:31778,47752:31779,47753:31780,47754:31781,47755:31784,47756:31785,47757:31787,47758:31788,47759:31789,47760:31790,47761:31791,47762:31792,47763:31793,47764:31794,47765:31795,47766:31796,47767:31797,47768:31798,47769:31799,47770:31801,47771:31802,47772:31803,47773:31804,47774:31805,47775:31806,47776:31810,47777:39608,47778:23401,47779:28023,47780:27686,47781:20133,47782:23475,47783:39559,47784:37219,47785:25000,47786:37039,47787:38889,47788:21547,47789:28085,47790:23506,47791:20989,47792:21898,47793:32597,47794:32752,47795:25788,47796:25421,47797:26097,47798:25022,47799:24717,47800:28938,47801:27735,47802:27721,47803:22831,47804:26477,47805:33322,47806:22741,47807:22158,47808:35946,47809:27627,47810:37085,47811:22909,47812:32791,47813:21495,47814:28009,47815:21621,47816:21917,47817:33655,47818:33743,47819:26680,47820:31166,47821:21644,47822:20309,47823:21512,47824:30418,47825:35977,47826:38402,47827:27827,47828:28088,47829:36203,47830:35088,47831:40548,47832:36154,47833:22079,47834:40657,47835:30165,47836:24456,47837:29408,47838:24680,47839:21756,47840:20136,47841:27178,47842:34913,47843:24658,47844:36720,47845:21700,47846:28888,47847:34425,47848:40511,47849:27946,47850:23439,47851:24344,47852:32418,47853:21897,47854:20399,47855:29492,47856:21564,47857:21402,47858:20505,47859:21518,47860:21628,47861:20046,47862:24573,47863:29786,47864:22774,47865:33899,47866:32993,47867:34676,47868:29392,47869:31946,47870:28246,47936:31811,47937:31812,47938:31813,47939:31814,47940:31815,47941:31816,47942:31817,47943:31818,47944:31819,47945:31820,47946:31822,47947:31823,47948:31824,47949:31825,47950:31826,47951:31827,47952:31828,47953:31829,47954:31830,47955:31831,47956:31832,47957:31833,47958:31834,47959:31835,47960:31836,47961:31837,47962:31838,47963:31839,47964:31840,47965:31841,47966:31842,47967:31843,47968:31844,47969:31845,47970:31846,47971:31847,47972:31848,47973:31849,47974:31850,47975:31851,47976:31852,47977:31853,47978:31854,47979:31855,47980:31856,47981:31857,47982:31858,47983:31861,47984:31862,47985:31863,47986:31864,47987:31865,47988:31866,47989:31870,47990:31871,47991:31872,47992:31873,47993:31874,47994:31875,47995:31876,47996:31877,47997:31878,47998:31879,48000:31880,48001:31882,48002:31883,48003:31884,48004:31885,48005:31886,48006:31887,48007:31888,48008:31891,48009:31892,48010:31894,48011:31897,48012:31898,48013:31899,48014:31904,48015:31905,48016:31907,48017:31910,48018:31911,48019:31912,48020:31913,48021:31915,48022:31916,48023:31917,48024:31919,48025:31920,48026:31924,48027:31925,48028:31926,48029:31927,48030:31928,48031:31930,48032:31931,48033:24359,48034:34382,48035:21804,48036:25252,48037:20114,48038:27818,48039:25143,48040:33457,48041:21719,48042:21326,48043:29502,48044:28369,48045:30011,48046:21010,48047:21270,48048:35805,48049:27088,48050:24458,48051:24576,48052:28142,48053:22351,48054:27426,48055:29615,48056:26707,48057:36824,48058:32531,48059:25442,48060:24739,48061:21796,48062:30186,48063:35938,48064:28949,48065:28067,48066:23462,48067:24187,48068:33618,48069:24908,48070:40644,48071:30970,48072:34647,48073:31783,48074:30343,48075:20976,48076:24822,48077:29004,48078:26179,48079:24140,48080:24653,48081:35854,48082:28784,48083:25381,48084:36745,48085:24509,48086:24674,48087:34516,48088:22238,48089:27585,48090:24724,48091:24935,48092:21321,48093:24800,48094:26214,48095:36159,48096:31229,48097:20250,48098:28905,48099:27719,48100:35763,48101:35826,48102:32472,48103:33636,48104:26127,48105:23130,48106:39746,48107:27985,48108:28151,48109:35905,48110:27963,48111:20249,48112:28779,48113:33719,48114:25110,48115:24785,48116:38669,48117:36135,48118:31096,48119:20987,48120:22334,48121:22522,48122:26426,48123:30072,48124:31293,48125:31215,48126:31637,48192:31935,48193:31936,48194:31938,48195:31939,48196:31940,48197:31942,48198:31945,48199:31947,48200:31950,48201:31951,48202:31952,48203:31953,48204:31954,48205:31955,48206:31956,48207:31960,48208:31962,48209:31963,48210:31965,48211:31966,48212:31969,48213:31970,48214:31971,48215:31972,48216:31973,48217:31974,48218:31975,48219:31977,48220:31978,48221:31979,48222:31980,48223:31981,48224:31982,48225:31984,48226:31985,48227:31986,48228:31987,48229:31988,48230:31989,48231:31990,48232:31991,48233:31993,48234:31994,48235:31996,48236:31997,48237:31998,48238:31999,48239:32000,48240:32001,48241:32002,48242:32003,48243:32004,48244:32005,48245:32006,48246:32007,48247:32008,48248:32009,48249:32011,48250:32012,48251:32013,48252:32014,48253:32015,48254:32016,48256:32017,48257:32018,48258:32019,48259:32020,48260:32021,48261:32022,48262:32023,48263:32024,48264:32025,48265:32026,48266:32027,48267:32028,48268:32029,48269:32030,48270:32031,48271:32033,48272:32035,48273:32036,48274:32037,48275:32038,48276:32040,48277:32041,48278:32042,48279:32044,48280:32045,48281:32046,48282:32048,48283:32049,48284:32050,48285:32051,48286:32052,48287:32053,48288:32054,48289:32908,48290:39269,48291:36857,48292:28608,48293:35749,48294:40481,48295:23020,48296:32489,48297:32521,48298:21513,48299:26497,48300:26840,48301:36753,48302:31821,48303:38598,48304:21450,48305:24613,48306:30142,48307:27762,48308:21363,48309:23241,48310:32423,48311:25380,48312:20960,48313:33034,48314:24049,48315:34015,48316:25216,48317:20864,48318:23395,48319:20238,48320:31085,48321:21058,48322:24760,48323:27982,48324:23492,48325:23490,48326:35745,48327:35760,48328:26082,48329:24524,48330:38469,48331:22931,48332:32487,48333:32426,48334:22025,48335:26551,48336:22841,48337:20339,48338:23478,48339:21152,48340:33626,48341:39050,48342:36158,48343:30002,48344:38078,48345:20551,48346:31292,48347:20215,48348:26550,48349:39550,48350:23233,48351:27516,48352:30417,48353:22362,48354:23574,48355:31546,48356:38388,48357:29006,48358:20860,48359:32937,48360:33392,48361:22904,48362:32516,48363:33575,48364:26816,48365:26604,48366:30897,48367:30839,48368:25315,48369:25441,48370:31616,48371:20461,48372:21098,48373:20943,48374:33616,48375:27099,48376:37492,48377:36341,48378:36145,48379:35265,48380:38190,48381:31661,48382:20214,48448:32055,48449:32056,48450:32057,48451:32058,48452:32059,48453:32060,48454:32061,48455:32062,48456:32063,48457:32064,48458:32065,48459:32066,48460:32067,48461:32068,48462:32069,48463:32070,48464:32071,48465:32072,48466:32073,48467:32074,48468:32075,48469:32076,48470:32077,48471:32078,48472:32079,48473:32080,48474:32081,48475:32082,48476:32083,48477:32084,48478:32085,48479:32086,48480:32087,48481:32088,48482:32089,48483:32090,48484:32091,48485:32092,48486:32093,48487:32094,48488:32095,48489:32096,48490:32097,48491:32098,48492:32099,48493:32100,48494:32101,48495:32102,48496:32103,48497:32104,48498:32105,48499:32106,48500:32107,48501:32108,48502:32109,48503:32111,48504:32112,48505:32113,48506:32114,48507:32115,48508:32116,48509:32117,48510:32118,48512:32120,48513:32121,48514:32122,48515:32123,48516:32124,48517:32125,48518:32126,48519:32127,48520:32128,48521:32129,48522:32130,48523:32131,48524:32132,48525:32133,48526:32134,48527:32135,48528:32136,48529:32137,48530:32138,48531:32139,48532:32140,48533:32141,48534:32142,48535:32143,48536:32144,48537:32145,48538:32146,48539:32147,48540:32148,48541:32149,48542:32150,48543:32151,48544:32152,48545:20581,48546:33328,48547:21073,48548:39279,48549:28176,48550:28293,48551:28071,48552:24314,48553:20725,48554:23004,48555:23558,48556:27974,48557:27743,48558:30086,48559:33931,48560:26728,48561:22870,48562:35762,48563:21280,48564:37233,48565:38477,48566:34121,48567:26898,48568:30977,48569:28966,48570:33014,48571:20132,48572:37066,48573:27975,48574:39556,48575:23047,48576:22204,48577:25605,48578:38128,48579:30699,48580:20389,48581:33050,48582:29409,48583:35282,48584:39290,48585:32564,48586:32478,48587:21119,48588:25945,48589:37237,48590:36735,48591:36739,48592:21483,48593:31382,48594:25581,48595:25509,48596:30342,48597:31224,48598:34903,48599:38454,48600:25130,48601:21163,48602:33410,48603:26708,48604:26480,48605:25463,48606:30571,48607:31469,48608:27905,48609:32467,48610:35299,48611:22992,48612:25106,48613:34249,48614:33445,48615:30028,48616:20511,48617:20171,48618:30117,48619:35819,48620:23626,48621:24062,48622:31563,48623:26020,48624:37329,48625:20170,48626:27941,48627:35167,48628:32039,48629:38182,48630:20165,48631:35880,48632:36827,48633:38771,48634:26187,48635:31105,48636:36817,48637:28908,48638:28024,48704:32153,48705:32154,48706:32155,48707:32156,48708:32157,48709:32158,48710:32159,48711:32160,48712:32161,48713:32162,48714:32163,48715:32164,48716:32165,48717:32167,48718:32168,48719:32169,48720:32170,48721:32171,48722:32172,48723:32173,48724:32175,48725:32176,48726:32177,48727:32178,48728:32179,48729:32180,48730:32181,48731:32182,48732:32183,48733:32184,48734:32185,48735:32186,48736:32187,48737:32188,48738:32189,48739:32190,48740:32191,48741:32192,48742:32193,48743:32194,48744:32195,48745:32196,48746:32197,48747:32198,48748:32199,48749:32200,48750:32201,48751:32202,48752:32203,48753:32204,48754:32205,48755:32206,48756:32207,48757:32208,48758:32209,48759:32210,48760:32211,48761:32212,48762:32213,48763:32214,48764:32215,48765:32216,48766:32217,48768:32218,48769:32219,48770:32220,48771:32221,48772:32222,48773:32223,48774:32224,48775:32225,48776:32226,48777:32227,48778:32228,48779:32229,48780:32230,48781:32231,48782:32232,48783:32233,48784:32234,48785:32235,48786:32236,48787:32237,48788:32238,48789:32239,48790:32240,48791:32241,48792:32242,48793:32243,48794:32244,48795:32245,48796:32246,48797:32247,48798:32248,48799:32249,48800:32250,48801:23613,48802:21170,48803:33606,48804:20834,48805:33550,48806:30555,48807:26230,48808:40120,48809:20140,48810:24778,48811:31934,48812:31923,48813:32463,48814:20117,48815:35686,48816:26223,48817:39048,48818:38745,48819:22659,48820:25964,48821:38236,48822:24452,48823:30153,48824:38742,48825:31455,48826:31454,48827:20928,48828:28847,48829:31384,48830:25578,48831:31350,48832:32416,48833:29590,48834:38893,48835:20037,48836:28792,48837:20061,48838:37202,48839:21417,48840:25937,48841:26087,48842:33276,48843:33285,48844:21646,48845:23601,48846:30106,48847:38816,48848:25304,48849:29401,48850:30141,48851:23621,48852:39545,48853:33738,48854:23616,48855:21632,48856:30697,48857:20030,48858:27822,48859:32858,48860:25298,48861:25454,48862:24040,48863:20855,48864:36317,48865:36382,48866:38191,48867:20465,48868:21477,48869:24807,48870:28844,48871:21095,48872:25424,48873:40515,48874:23071,48875:20518,48876:30519,48877:21367,48878:32482,48879:25733,48880:25899,48881:25225,48882:25496,48883:20500,48884:29237,48885:35273,48886:20915,48887:35776,48888:32477,48889:22343,48890:33740,48891:38055,48892:20891,48893:21531,48894:23803,48960:32251,48961:32252,48962:32253,48963:32254,48964:32255,48965:32256,48966:32257,48967:32258,48968:32259,48969:32260,48970:32261,48971:32262,48972:32263,48973:32264,48974:32265,48975:32266,48976:32267,48977:32268,48978:32269,48979:32270,48980:32271,48981:32272,48982:32273,48983:32274,48984:32275,48985:32276,48986:32277,48987:32278,48988:32279,48989:32280,48990:32281,48991:32282,48992:32283,48993:32284,48994:32285,48995:32286,48996:32287,48997:32288,48998:32289,48999:32290,49000:32291,49001:32292,49002:32293,49003:32294,49004:32295,49005:32296,49006:32297,49007:32298,49008:32299,49009:32300,49010:32301,49011:32302,49012:32303,49013:32304,49014:32305,49015:32306,49016:32307,49017:32308,49018:32309,49019:32310,49020:32311,49021:32312,49022:32313,49024:32314,49025:32316,49026:32317,49027:32318,49028:32319,49029:32320,49030:32322,49031:32323,49032:32324,49033:32325,49034:32326,49035:32328,49036:32329,49037:32330,49038:32331,49039:32332,49040:32333,49041:32334,49042:32335,49043:32336,49044:32337,49045:32338,49046:32339,49047:32340,49048:32341,49049:32342,49050:32343,49051:32344,49052:32345,49053:32346,49054:32347,49055:32348,49056:32349,49057:20426,49058:31459,49059:27994,49060:37089,49061:39567,49062:21888,49063:21654,49064:21345,49065:21679,49066:24320,49067:25577,49068:26999,49069:20975,49070:24936,49071:21002,49072:22570,49073:21208,49074:22350,49075:30733,49076:30475,49077:24247,49078:24951,49079:31968,49080:25179,49081:25239,49082:20130,49083:28821,49084:32771,49085:25335,49086:28900,49087:38752,49088:22391,49089:33499,49090:26607,49091:26869,49092:30933,49093:39063,49094:31185,49095:22771,49096:21683,49097:21487,49098:28212,49099:20811,49100:21051,49101:23458,49102:35838,49103:32943,49104:21827,49105:22438,49106:24691,49107:22353,49108:21549,49109:31354,49110:24656,49111:23380,49112:25511,49113:25248,49114:21475,49115:25187,49116:23495,49117:26543,49118:21741,49119:31391,49120:33510,49121:37239,49122:24211,49123:35044,49124:22840,49125:22446,49126:25358,49127:36328,49128:33007,49129:22359,49130:31607,49131:20393,49132:24555,49133:23485,49134:27454,49135:21281,49136:31568,49137:29378,49138:26694,49139:30719,49140:30518,49141:26103,49142:20917,49143:20111,49144:30420,49145:23743,49146:31397,49147:33909,49148:22862,49149:39745,49150:20608,49216:32350,49217:32351,49218:32352,49219:32353,49220:32354,49221:32355,49222:32356,49223:32357,49224:32358,49225:32359,49226:32360,49227:32361,49228:32362,49229:32363,49230:32364,49231:32365,49232:32366,49233:32367,49234:32368,49235:32369,49236:32370,49237:32371,49238:32372,49239:32373,49240:32374,49241:32375,49242:32376,49243:32377,49244:32378,49245:32379,49246:32380,49247:32381,49248:32382,49249:32383,49250:32384,49251:32385,49252:32387,49253:32388,49254:32389,49255:32390,49256:32391,49257:32392,49258:32393,49259:32394,49260:32395,49261:32396,49262:32397,49263:32398,49264:32399,49265:32400,49266:32401,49267:32402,49268:32403,49269:32404,49270:32405,49271:32406,49272:32407,49273:32408,49274:32409,49275:32410,49276:32412,49277:32413,49278:32414,49280:32430,49281:32436,49282:32443,49283:32444,49284:32470,49285:32484,49286:32492,49287:32505,49288:32522,49289:32528,49290:32542,49291:32567,49292:32569,49293:32571,49294:32572,49295:32573,49296:32574,49297:32575,49298:32576,49299:32577,49300:32579,49301:32582,49302:32583,49303:32584,49304:32585,49305:32586,49306:32587,49307:32588,49308:32589,49309:32590,49310:32591,49311:32594,49312:32595,49313:39304,49314:24871,49315:28291,49316:22372,49317:26118,49318:25414,49319:22256,49320:25324,49321:25193,49322:24275,49323:38420,49324:22403,49325:25289,49326:21895,49327:34593,49328:33098,49329:36771,49330:21862,49331:33713,49332:26469,49333:36182,49334:34013,49335:23146,49336:26639,49337:25318,49338:31726,49339:38417,49340:20848,49341:28572,49342:35888,49343:25597,49344:35272,49345:25042,49346:32518,49347:28866,49348:28389,49349:29701,49350:27028,49351:29436,49352:24266,49353:37070,49354:26391,49355:28010,49356:25438,49357:21171,49358:29282,49359:32769,49360:20332,49361:23013,49362:37226,49363:28889,49364:28061,49365:21202,49366:20048,49367:38647,49368:38253,49369:34174,49370:30922,49371:32047,49372:20769,49373:22418,49374:25794,49375:32907,49376:31867,49377:27882,49378:26865,49379:26974,49380:20919,49381:21400,49382:26792,49383:29313,49384:40654,49385:31729,49386:29432,49387:31163,49388:28435,49389:29702,49390:26446,49391:37324,49392:40100,49393:31036,49394:33673,49395:33620,49396:21519,49397:26647,49398:20029,49399:21385,49400:21169,49401:30782,49402:21382,49403:21033,49404:20616,49405:20363,49406:20432,49472:32598,49473:32601,49474:32603,49475:32604,49476:32605,49477:32606,49478:32608,49479:32611,49480:32612,49481:32613,49482:32614,49483:32615,49484:32619,49485:32620,49486:32621,49487:32623,49488:32624,49489:32627,49490:32629,49491:32630,49492:32631,49493:32632,49494:32634,49495:32635,49496:32636,49497:32637,49498:32639,49499:32640,49500:32642,49501:32643,49502:32644,49503:32645,49504:32646,49505:32647,49506:32648,49507:32649,49508:32651,49509:32653,49510:32655,49511:32656,49512:32657,49513:32658,49514:32659,49515:32661,49516:32662,49517:32663,49518:32664,49519:32665,49520:32667,49521:32668,49522:32672,49523:32674,49524:32675,49525:32677,49526:32678,49527:32680,49528:32681,49529:32682,49530:32683,49531:32684,49532:32685,49533:32686,49534:32689,49536:32691,49537:32692,49538:32693,49539:32694,49540:32695,49541:32698,49542:32699,49543:32702,49544:32704,49545:32706,49546:32707,49547:32708,49548:32710,49549:32711,49550:32712,49551:32713,49552:32715,49553:32717,49554:32719,49555:32720,49556:32721,49557:32722,49558:32723,49559:32726,49560:32727,49561:32729,49562:32730,49563:32731,49564:32732,49565:32733,49566:32734,49567:32738,49568:32739,49569:30178,49570:31435,49571:31890,49572:27813,49573:38582,49574:21147,49575:29827,49576:21737,49577:20457,49578:32852,49579:33714,49580:36830,49581:38256,49582:24265,49583:24604,49584:28063,49585:24088,49586:25947,49587:33080,49588:38142,49589:24651,49590:28860,49591:32451,49592:31918,49593:20937,49594:26753,49595:31921,49596:33391,49597:20004,49598:36742,49599:37327,49600:26238,49601:20142,49602:35845,49603:25769,49604:32842,49605:20698,49606:30103,49607:29134,49608:23525,49609:36797,49610:28518,49611:20102,49612:25730,49613:38243,49614:24278,49615:26009,49616:21015,49617:35010,49618:28872,49619:21155,49620:29454,49621:29747,49622:26519,49623:30967,49624:38678,49625:20020,49626:37051,49627:40158,49628:28107,49629:20955,49630:36161,49631:21533,49632:25294,49633:29618,49634:33777,49635:38646,49636:40836,49637:38083,49638:20278,49639:32666,49640:20940,49641:28789,49642:38517,49643:23725,49644:39046,49645:21478,49646:20196,49647:28316,49648:29705,49649:27060,49650:30827,49651:39311,49652:30041,49653:21016,49654:30244,49655:27969,49656:26611,49657:20845,49658:40857,49659:32843,49660:21657,49661:31548,49662:31423,49728:32740,49729:32743,49730:32744,49731:32746,49732:32747,49733:32748,49734:32749,49735:32751,49736:32754,49737:32756,49738:32757,49739:32758,49740:32759,49741:32760,49742:32761,49743:32762,49744:32765,49745:32766,49746:32767,49747:32770,49748:32775,49749:32776,49750:32777,49751:32778,49752:32782,49753:32783,49754:32785,49755:32787,49756:32794,49757:32795,49758:32797,49759:32798,49760:32799,49761:32801,49762:32803,49763:32804,49764:32811,49765:32812,49766:32813,49767:32814,49768:32815,49769:32816,49770:32818,49771:32820,49772:32825,49773:32826,49774:32828,49775:32830,49776:32832,49777:32833,49778:32836,49779:32837,49780:32839,49781:32840,49782:32841,49783:32846,49784:32847,49785:32848,49786:32849,49787:32851,49788:32853,49789:32854,49790:32855,49792:32857,49793:32859,49794:32860,49795:32861,49796:32862,49797:32863,49798:32864,49799:32865,49800:32866,49801:32867,49802:32868,49803:32869,49804:32870,49805:32871,49806:32872,49807:32875,49808:32876,49809:32877,49810:32878,49811:32879,49812:32880,49813:32882,49814:32883,49815:32884,49816:32885,49817:32886,49818:32887,49819:32888,49820:32889,49821:32890,49822:32891,49823:32892,49824:32893,49825:38534,49826:22404,49827:25314,49828:38471,49829:27004,49830:23044,49831:25602,49832:31699,49833:28431,49834:38475,49835:33446,49836:21346,49837:39045,49838:24208,49839:28809,49840:25523,49841:21348,49842:34383,49843:40065,49844:40595,49845:30860,49846:38706,49847:36335,49848:36162,49849:40575,49850:28510,49851:31108,49852:24405,49853:38470,49854:25134,49855:39540,49856:21525,49857:38109,49858:20387,49859:26053,49860:23653,49861:23649,49862:32533,49863:34385,49864:27695,49865:24459,49866:29575,49867:28388,49868:32511,49869:23782,49870:25371,49871:23402,49872:28390,49873:21365,49874:20081,49875:25504,49876:30053,49877:25249,49878:36718,49879:20262,49880:20177,49881:27814,49882:32438,49883:35770,49884:33821,49885:34746,49886:32599,49887:36923,49888:38179,49889:31657,49890:39585,49891:35064,49892:33853,49893:27931,49894:39558,49895:32476,49896:22920,49897:40635,49898:29595,49899:30721,49900:34434,49901:39532,49902:39554,49903:22043,49904:21527,49905:22475,49906:20080,49907:40614,49908:21334,49909:36808,49910:33033,49911:30610,49912:39314,49913:34542,49914:28385,49915:34067,49916:26364,49917:24930,49918:28459,49984:32894,49985:32897,49986:32898,49987:32901,49988:32904,49989:32906,49990:32909,49991:32910,49992:32911,49993:32912,49994:32913,49995:32914,49996:32916,49997:32917,49998:32919,49999:32921,50000:32926,50001:32931,50002:32934,50003:32935,50004:32936,50005:32940,50006:32944,50007:32947,50008:32949,50009:32950,50010:32952,50011:32953,50012:32955,50013:32965,50014:32967,50015:32968,50016:32969,50017:32970,50018:32971,50019:32975,50020:32976,50021:32977,50022:32978,50023:32979,50024:32980,50025:32981,50026:32984,50027:32991,50028:32992,50029:32994,50030:32995,50031:32998,50032:33006,50033:33013,50034:33015,50035:33017,50036:33019,50037:33022,50038:33023,50039:33024,50040:33025,50041:33027,50042:33028,50043:33029,50044:33031,50045:33032,50046:33035,50048:33036,50049:33045,50050:33047,50051:33049,50052:33051,50053:33052,50054:33053,50055:33055,50056:33056,50057:33057,50058:33058,50059:33059,50060:33060,50061:33061,50062:33062,50063:33063,50064:33064,50065:33065,50066:33066,50067:33067,50068:33069,50069:33070,50070:33072,50071:33075,50072:33076,50073:33077,50074:33079,50075:33081,50076:33082,50077:33083,50078:33084,50079:33085,50080:33087,50081:35881,50082:33426,50083:33579,50084:30450,50085:27667,50086:24537,50087:33725,50088:29483,50089:33541,50090:38170,50091:27611,50092:30683,50093:38086,50094:21359,50095:33538,50096:20882,50097:24125,50098:35980,50099:36152,50100:20040,50101:29611,50102:26522,50103:26757,50104:37238,50105:38665,50106:29028,50107:27809,50108:30473,50109:23186,50110:38209,50111:27599,50112:32654,50113:26151,50114:23504,50115:22969,50116:23194,50117:38376,50118:38391,50119:20204,50120:33804,50121:33945,50122:27308,50123:30431,50124:38192,50125:29467,50126:26790,50127:23391,50128:30511,50129:37274,50130:38753,50131:31964,50132:36855,50133:35868,50134:24357,50135:31859,50136:31192,50137:35269,50138:27852,50139:34588,50140:23494,50141:24130,50142:26825,50143:30496,50144:32501,50145:20885,50146:20813,50147:21193,50148:23081,50149:32517,50150:38754,50151:33495,50152:25551,50153:30596,50154:34256,50155:31186,50156:28218,50157:24217,50158:22937,50159:34065,50160:28781,50161:27665,50162:25279,50163:30399,50164:25935,50165:24751,50166:38397,50167:26126,50168:34719,50169:40483,50170:38125,50171:21517,50172:21629,50173:35884,50174:25720,50240:33088,50241:33089,50242:33090,50243:33091,50244:33092,50245:33093,50246:33095,50247:33097,50248:33101,50249:33102,50250:33103,50251:33106,50252:33110,50253:33111,50254:33112,50255:33115,50256:33116,50257:33117,50258:33118,50259:33119,50260:33121,50261:33122,50262:33123,50263:33124,50264:33126,50265:33128,50266:33130,50267:33131,50268:33132,50269:33135,50270:33138,50271:33139,50272:33141,50273:33142,50274:33143,50275:33144,50276:33153,50277:33155,50278:33156,50279:33157,50280:33158,50281:33159,50282:33161,50283:33163,50284:33164,50285:33165,50286:33166,50287:33168,50288:33170,50289:33171,50290:33172,50291:33173,50292:33174,50293:33175,50294:33177,50295:33178,50296:33182,50297:33183,50298:33184,50299:33185,50300:33186,50301:33188,50302:33189,50304:33191,50305:33193,50306:33195,50307:33196,50308:33197,50309:33198,50310:33199,50311:33200,50312:33201,50313:33202,50314:33204,50315:33205,50316:33206,50317:33207,50318:33208,50319:33209,50320:33212,50321:33213,50322:33214,50323:33215,50324:33220,50325:33221,50326:33223,50327:33224,50328:33225,50329:33227,50330:33229,50331:33230,50332:33231,50333:33232,50334:33233,50335:33234,50336:33235,50337:25721,50338:34321,50339:27169,50340:33180,50341:30952,50342:25705,50343:39764,50344:25273,50345:26411,50346:33707,50347:22696,50348:40664,50349:27819,50350:28448,50351:23518,50352:38476,50353:35851,50354:29279,50355:26576,50356:25287,50357:29281,50358:20137,50359:22982,50360:27597,50361:22675,50362:26286,50363:24149,50364:21215,50365:24917,50366:26408,50367:30446,50368:30566,50369:29287,50370:31302,50371:25343,50372:21738,50373:21584,50374:38048,50375:37027,50376:23068,50377:32435,50378:27670,50379:20035,50380:22902,50381:32784,50382:22856,50383:21335,50384:30007,50385:38590,50386:22218,50387:25376,50388:33041,50389:24700,50390:38393,50391:28118,50392:21602,50393:39297,50394:20869,50395:23273,50396:33021,50397:22958,50398:38675,50399:20522,50400:27877,50401:23612,50402:25311,50403:20320,50404:21311,50405:33147,50406:36870,50407:28346,50408:34091,50409:25288,50410:24180,50411:30910,50412:25781,50413:25467,50414:24565,50415:23064,50416:37247,50417:40479,50418:23615,50419:25423,50420:32834,50421:23421,50422:21870,50423:38218,50424:38221,50425:28037,50426:24744,50427:26592,50428:29406,50429:20957,50430:23425,50496:33236,50497:33237,50498:33238,50499:33239,50500:33240,50501:33241,50502:33242,50503:33243,50504:33244,50505:33245,50506:33246,50507:33247,50508:33248,50509:33249,50510:33250,50511:33252,50512:33253,50513:33254,50514:33256,50515:33257,50516:33259,50517:33262,50518:33263,50519:33264,50520:33265,50521:33266,50522:33269,50523:33270,50524:33271,50525:33272,50526:33273,50527:33274,50528:33277,50529:33279,50530:33283,50531:33287,50532:33288,50533:33289,50534:33290,50535:33291,50536:33294,50537:33295,50538:33297,50539:33299,50540:33301,50541:33302,50542:33303,50543:33304,50544:33305,50545:33306,50546:33309,50547:33312,50548:33316,50549:33317,50550:33318,50551:33319,50552:33321,50553:33326,50554:33330,50555:33338,50556:33340,50557:33341,50558:33343,50560:33344,50561:33345,50562:33346,50563:33347,50564:33349,50565:33350,50566:33352,50567:33354,50568:33356,50569:33357,50570:33358,50571:33360,50572:33361,50573:33362,50574:33363,50575:33364,50576:33365,50577:33366,50578:33367,50579:33369,50580:33371,50581:33372,50582:33373,50583:33374,50584:33376,50585:33377,50586:33378,50587:33379,50588:33380,50589:33381,50590:33382,50591:33383,50592:33385,50593:25319,50594:27870,50595:29275,50596:25197,50597:38062,50598:32445,50599:33043,50600:27987,50601:20892,50602:24324,50603:22900,50604:21162,50605:24594,50606:22899,50607:26262,50608:34384,50609:30111,50610:25386,50611:25062,50612:31983,50613:35834,50614:21734,50615:27431,50616:40485,50617:27572,50618:34261,50619:21589,50620:20598,50621:27812,50622:21866,50623:36276,50624:29228,50625:24085,50626:24597,50627:29750,50628:25293,50629:25490,50630:29260,50631:24472,50632:28227,50633:27966,50634:25856,50635:28504,50636:30424,50637:30928,50638:30460,50639:30036,50640:21028,50641:21467,50642:20051,50643:24222,50644:26049,50645:32810,50646:32982,50647:25243,50648:21638,50649:21032,50650:28846,50651:34957,50652:36305,50653:27873,50654:21624,50655:32986,50656:22521,50657:35060,50658:36180,50659:38506,50660:37197,50661:20329,50662:27803,50663:21943,50664:30406,50665:30768,50666:25256,50667:28921,50668:28558,50669:24429,50670:34028,50671:26842,50672:30844,50673:31735,50674:33192,50675:26379,50676:40527,50677:25447,50678:30896,50679:22383,50680:30738,50681:38713,50682:25209,50683:25259,50684:21128,50685:29749,50686:27607,50752:33386,50753:33387,50754:33388,50755:33389,50756:33393,50757:33397,50758:33398,50759:33399,50760:33400,50761:33403,50762:33404,50763:33408,50764:33409,50765:33411,50766:33413,50767:33414,50768:33415,50769:33417,50770:33420,50771:33424,50772:33427,50773:33428,50774:33429,50775:33430,50776:33434,50777:33435,50778:33438,50779:33440,50780:33442,50781:33443,50782:33447,50783:33458,50784:33461,50785:33462,50786:33466,50787:33467,50788:33468,50789:33471,50790:33472,50791:33474,50792:33475,50793:33477,50794:33478,50795:33481,50796:33488,50797:33494,50798:33497,50799:33498,50800:33501,50801:33506,50802:33511,50803:33512,50804:33513,50805:33514,50806:33516,50807:33517,50808:33518,50809:33520,50810:33522,50811:33523,50812:33525,50813:33526,50814:33528,50816:33530,50817:33532,50818:33533,50819:33534,50820:33535,50821:33536,50822:33546,50823:33547,50824:33549,50825:33552,50826:33554,50827:33555,50828:33558,50829:33560,50830:33561,50831:33565,50832:33566,50833:33567,50834:33568,50835:33569,50836:33570,50837:33571,50838:33572,50839:33573,50840:33574,50841:33577,50842:33578,50843:33582,50844:33584,50845:33586,50846:33591,50847:33595,50848:33597,50849:21860,50850:33086,50851:30130,50852:30382,50853:21305,50854:30174,50855:20731,50856:23617,50857:35692,50858:31687,50859:20559,50860:29255,50861:39575,50862:39128,50863:28418,50864:29922,50865:31080,50866:25735,50867:30629,50868:25340,50869:39057,50870:36139,50871:21697,50872:32856,50873:20050,50874:22378,50875:33529,50876:33805,50877:24179,50878:20973,50879:29942,50880:35780,50881:23631,50882:22369,50883:27900,50884:39047,50885:23110,50886:30772,50887:39748,50888:36843,50889:31893,50890:21078,50891:25169,50892:38138,50893:20166,50894:33670,50895:33889,50896:33769,50897:33970,50898:22484,50899:26420,50900:22275,50901:26222,50902:28006,50903:35889,50904:26333,50905:28689,50906:26399,50907:27450,50908:26646,50909:25114,50910:22971,50911:19971,50912:20932,50913:28422,50914:26578,50915:27791,50916:20854,50917:26827,50918:22855,50919:27495,50920:30054,50921:23822,50922:33040,50923:40784,50924:26071,50925:31048,50926:31041,50927:39569,50928:36215,50929:23682,50930:20062,50931:20225,50932:21551,50933:22865,50934:30732,50935:22120,50936:27668,50937:36804,50938:24323,50939:27773,50940:27875,50941:35755,50942:25488,51008:33598,51009:33599,51010:33601,51011:33602,51012:33604,51013:33605,51014:33608,51015:33610,51016:33611,51017:33612,51018:33613,51019:33614,51020:33619,51021:33621,51022:33622,51023:33623,51024:33624,51025:33625,51026:33629,51027:33634,51028:33648,51029:33649,51030:33650,51031:33651,51032:33652,51033:33653,51034:33654,51035:33657,51036:33658,51037:33662,51038:33663,51039:33664,51040:33665,51041:33666,51042:33667,51043:33668,51044:33671,51045:33672,51046:33674,51047:33675,51048:33676,51049:33677,51050:33679,51051:33680,51052:33681,51053:33684,51054:33685,51055:33686,51056:33687,51057:33689,51058:33690,51059:33693,51060:33695,51061:33697,51062:33698,51063:33699,51064:33700,51065:33701,51066:33702,51067:33703,51068:33708,51069:33709,51070:33710,51072:33711,51073:33717,51074:33723,51075:33726,51076:33727,51077:33730,51078:33731,51079:33732,51080:33734,51081:33736,51082:33737,51083:33739,51084:33741,51085:33742,51086:33744,51087:33745,51088:33746,51089:33747,51090:33749,51091:33751,51092:33753,51093:33754,51094:33755,51095:33758,51096:33762,51097:33763,51098:33764,51099:33766,51100:33767,51101:33768,51102:33771,51103:33772,51104:33773,51105:24688,51106:27965,51107:29301,51108:25190,51109:38030,51110:38085,51111:21315,51112:36801,51113:31614,51114:20191,51115:35878,51116:20094,51117:40660,51118:38065,51119:38067,51120:21069,51121:28508,51122:36963,51123:27973,51124:35892,51125:22545,51126:23884,51127:27424,51128:27465,51129:26538,51130:21595,51131:33108,51132:32652,51133:22681,51134:34103,51135:24378,51136:25250,51137:27207,51138:38201,51139:25970,51140:24708,51141:26725,51142:30631,51143:20052,51144:20392,51145:24039,51146:38808,51147:25772,51148:32728,51149:23789,51150:20431,51151:31373,51152:20999,51153:33540,51154:19988,51155:24623,51156:31363,51157:38054,51158:20405,51159:20146,51160:31206,51161:29748,51162:21220,51163:33465,51164:25810,51165:31165,51166:23517,51167:27777,51168:38738,51169:36731,51170:27682,51171:20542,51172:21375,51173:28165,51174:25806,51175:26228,51176:27696,51177:24773,51178:39031,51179:35831,51180:24198,51181:29756,51182:31351,51183:31179,51184:19992,51185:37041,51186:29699,51187:27714,51188:22234,51189:37195,51190:27845,51191:36235,51192:21306,51193:34502,51194:26354,51195:36527,51196:23624,51197:39537,51198:28192,51264:33774,51265:33775,51266:33779,51267:33780,51268:33781,51269:33782,51270:33783,51271:33786,51272:33787,51273:33788,51274:33790,51275:33791,51276:33792,51277:33794,51278:33797,51279:33799,51280:33800,51281:33801,51282:33802,51283:33808,51284:33810,51285:33811,51286:33812,51287:33813,51288:33814,51289:33815,51290:33817,51291:33818,51292:33819,51293:33822,51294:33823,51295:33824,51296:33825,51297:33826,51298:33827,51299:33833,51300:33834,51301:33835,51302:33836,51303:33837,51304:33838,51305:33839,51306:33840,51307:33842,51308:33843,51309:33844,51310:33845,51311:33846,51312:33847,51313:33849,51314:33850,51315:33851,51316:33854,51317:33855,51318:33856,51319:33857,51320:33858,51321:33859,51322:33860,51323:33861,51324:33863,51325:33864,51326:33865,51328:33866,51329:33867,51330:33868,51331:33869,51332:33870,51333:33871,51334:33872,51335:33874,51336:33875,51337:33876,51338:33877,51339:33878,51340:33880,51341:33885,51342:33886,51343:33887,51344:33888,51345:33890,51346:33892,51347:33893,51348:33894,51349:33895,51350:33896,51351:33898,51352:33902,51353:33903,51354:33904,51355:33906,51356:33908,51357:33911,51358:33913,51359:33915,51360:33916,51361:21462,51362:23094,51363:40843,51364:36259,51365:21435,51366:22280,51367:39079,51368:26435,51369:37275,51370:27849,51371:20840,51372:30154,51373:25331,51374:29356,51375:21048,51376:21149,51377:32570,51378:28820,51379:30264,51380:21364,51381:40522,51382:27063,51383:30830,51384:38592,51385:35033,51386:32676,51387:28982,51388:29123,51389:20873,51390:26579,51391:29924,51392:22756,51393:25880,51394:22199,51395:35753,51396:39286,51397:25200,51398:32469,51399:24825,51400:28909,51401:22764,51402:20161,51403:20154,51404:24525,51405:38887,51406:20219,51407:35748,51408:20995,51409:22922,51410:32427,51411:25172,51412:20173,51413:26085,51414:25102,51415:33592,51416:33993,51417:33635,51418:34701,51419:29076,51420:28342,51421:23481,51422:32466,51423:20887,51424:25545,51425:26580,51426:32905,51427:33593,51428:34837,51429:20754,51430:23418,51431:22914,51432:36785,51433:20083,51434:27741,51435:20837,51436:35109,51437:36719,51438:38446,51439:34122,51440:29790,51441:38160,51442:38384,51443:28070,51444:33509,51445:24369,51446:25746,51447:27922,51448:33832,51449:33134,51450:40131,51451:22622,51452:36187,51453:19977,51454:21441,51520:33917,51521:33918,51522:33919,51523:33920,51524:33921,51525:33923,51526:33924,51527:33925,51528:33926,51529:33930,51530:33933,51531:33935,51532:33936,51533:33937,51534:33938,51535:33939,51536:33940,51537:33941,51538:33942,51539:33944,51540:33946,51541:33947,51542:33949,51543:33950,51544:33951,51545:33952,51546:33954,51547:33955,51548:33956,51549:33957,51550:33958,51551:33959,51552:33960,51553:33961,51554:33962,51555:33963,51556:33964,51557:33965,51558:33966,51559:33968,51560:33969,51561:33971,51562:33973,51563:33974,51564:33975,51565:33979,51566:33980,51567:33982,51568:33984,51569:33986,51570:33987,51571:33989,51572:33990,51573:33991,51574:33992,51575:33995,51576:33996,51577:33998,51578:33999,51579:34002,51580:34004,51581:34005,51582:34007,51584:34008,51585:34009,51586:34010,51587:34011,51588:34012,51589:34014,51590:34017,51591:34018,51592:34020,51593:34023,51594:34024,51595:34025,51596:34026,51597:34027,51598:34029,51599:34030,51600:34031,51601:34033,51602:34034,51603:34035,51604:34036,51605:34037,51606:34038,51607:34039,51608:34040,51609:34041,51610:34042,51611:34043,51612:34045,51613:34046,51614:34048,51615:34049,51616:34050,51617:20254,51618:25955,51619:26705,51620:21971,51621:20007,51622:25620,51623:39578,51624:25195,51625:23234,51626:29791,51627:33394,51628:28073,51629:26862,51630:20711,51631:33678,51632:30722,51633:26432,51634:21049,51635:27801,51636:32433,51637:20667,51638:21861,51639:29022,51640:31579,51641:26194,51642:29642,51643:33515,51644:26441,51645:23665,51646:21024,51647:29053,51648:34923,51649:38378,51650:38485,51651:25797,51652:36193,51653:33203,51654:21892,51655:27733,51656:25159,51657:32558,51658:22674,51659:20260,51660:21830,51661:36175,51662:26188,51663:19978,51664:23578,51665:35059,51666:26786,51667:25422,51668:31245,51669:28903,51670:33421,51671:21242,51672:38902,51673:23569,51674:21736,51675:37045,51676:32461,51677:22882,51678:36170,51679:34503,51680:33292,51681:33293,51682:36198,51683:25668,51684:23556,51685:24913,51686:28041,51687:31038,51688:35774,51689:30775,51690:30003,51691:21627,51692:20280,51693:36523,51694:28145,51695:23072,51696:32453,51697:31070,51698:27784,51699:23457,51700:23158,51701:29978,51702:32958,51703:24910,51704:28183,51705:22768,51706:29983,51707:29989,51708:29298,51709:21319,51710:32499,51776:34051,51777:34052,51778:34053,51779:34054,51780:34055,51781:34056,51782:34057,51783:34058,51784:34059,51785:34061,51786:34062,51787:34063,51788:34064,51789:34066,51790:34068,51791:34069,51792:34070,51793:34072,51794:34073,51795:34075,51796:34076,51797:34077,51798:34078,51799:34080,51800:34082,51801:34083,51802:34084,51803:34085,51804:34086,51805:34087,51806:34088,51807:34089,51808:34090,51809:34093,51810:34094,51811:34095,51812:34096,51813:34097,51814:34098,51815:34099,51816:34100,51817:34101,51818:34102,51819:34110,51820:34111,51821:34112,51822:34113,51823:34114,51824:34116,51825:34117,51826:34118,51827:34119,51828:34123,51829:34124,51830:34125,51831:34126,51832:34127,51833:34128,51834:34129,51835:34130,51836:34131,51837:34132,51838:34133,51840:34135,51841:34136,51842:34138,51843:34139,51844:34140,51845:34141,51846:34143,51847:34144,51848:34145,51849:34146,51850:34147,51851:34149,51852:34150,51853:34151,51854:34153,51855:34154,51856:34155,51857:34156,51858:34157,51859:34158,51860:34159,51861:34160,51862:34161,51863:34163,51864:34165,51865:34166,51866:34167,51867:34168,51868:34172,51869:34173,51870:34175,51871:34176,51872:34177,51873:30465,51874:30427,51875:21097,51876:32988,51877:22307,51878:24072,51879:22833,51880:29422,51881:26045,51882:28287,51883:35799,51884:23608,51885:34417,51886:21313,51887:30707,51888:25342,51889:26102,51890:20160,51891:39135,51892:34432,51893:23454,51894:35782,51895:21490,51896:30690,51897:20351,51898:23630,51899:39542,51900:22987,51901:24335,51902:31034,51903:22763,51904:19990,51905:26623,51906:20107,51907:25325,51908:35475,51909:36893,51910:21183,51911:26159,51912:21980,51913:22124,51914:36866,51915:20181,51916:20365,51917:37322,51918:39280,51919:27663,51920:24066,51921:24643,51922:23460,51923:35270,51924:35797,51925:25910,51926:25163,51927:39318,51928:23432,51929:23551,51930:25480,51931:21806,51932:21463,51933:30246,51934:20861,51935:34092,51936:26530,51937:26803,51938:27530,51939:25234,51940:36755,51941:21460,51942:33298,51943:28113,51944:30095,51945:20070,51946:36174,51947:23408,51948:29087,51949:34223,51950:26257,51951:26329,51952:32626,51953:34560,51954:40653,51955:40736,51956:23646,51957:26415,51958:36848,51959:26641,51960:26463,51961:25101,51962:31446,51963:22661,51964:24246,51965:25968,51966:28465,52032:34178,52033:34179,52034:34182,52035:34184,52036:34185,52037:34186,52038:34187,52039:34188,52040:34189,52041:34190,52042:34192,52043:34193,52044:34194,52045:34195,52046:34196,52047:34197,52048:34198,52049:34199,52050:34200,52051:34201,52052:34202,52053:34205,52054:34206,52055:34207,52056:34208,52057:34209,52058:34210,52059:34211,52060:34213,52061:34214,52062:34215,52063:34217,52064:34219,52065:34220,52066:34221,52067:34225,52068:34226,52069:34227,52070:34228,52071:34229,52072:34230,52073:34232,52074:34234,52075:34235,52076:34236,52077:34237,52078:34238,52079:34239,52080:34240,52081:34242,52082:34243,52083:34244,52084:34245,52085:34246,52086:34247,52087:34248,52088:34250,52089:34251,52090:34252,52091:34253,52092:34254,52093:34257,52094:34258,52096:34260,52097:34262,52098:34263,52099:34264,52100:34265,52101:34266,52102:34267,52103:34269,52104:34270,52105:34271,52106:34272,52107:34273,52108:34274,52109:34275,52110:34277,52111:34278,52112:34279,52113:34280,52114:34282,52115:34283,52116:34284,52117:34285,52118:34286,52119:34287,52120:34288,52121:34289,52122:34290,52123:34291,52124:34292,52125:34293,52126:34294,52127:34295,52128:34296,52129:24661,52130:21047,52131:32781,52132:25684,52133:34928,52134:29993,52135:24069,52136:26643,52137:25332,52138:38684,52139:21452,52140:29245,52141:35841,52142:27700,52143:30561,52144:31246,52145:21550,52146:30636,52147:39034,52148:33308,52149:35828,52150:30805,52151:26388,52152:28865,52153:26031,52154:25749,52155:22070,52156:24605,52157:31169,52158:21496,52159:19997,52160:27515,52161:32902,52162:23546,52163:21987,52164:22235,52165:20282,52166:20284,52167:39282,52168:24051,52169:26494,52170:32824,52171:24578,52172:39042,52173:36865,52174:23435,52175:35772,52176:35829,52177:25628,52178:33368,52179:25822,52180:22013,52181:33487,52182:37221,52183:20439,52184:32032,52185:36895,52186:31903,52187:20723,52188:22609,52189:28335,52190:23487,52191:35785,52192:32899,52193:37240,52194:33948,52195:31639,52196:34429,52197:38539,52198:38543,52199:32485,52200:39635,52201:30862,52202:23681,52203:31319,52204:36930,52205:38567,52206:31071,52207:23385,52208:25439,52209:31499,52210:34001,52211:26797,52212:21766,52213:32553,52214:29712,52215:32034,52216:38145,52217:25152,52218:22604,52219:20182,52220:23427,52221:22905,52222:22612,52288:34297,52289:34298,52290:34300,52291:34301,52292:34302,52293:34304,52294:34305,52295:34306,52296:34307,52297:34308,52298:34310,52299:34311,52300:34312,52301:34313,52302:34314,52303:34315,52304:34316,52305:34317,52306:34318,52307:34319,52308:34320,52309:34322,52310:34323,52311:34324,52312:34325,52313:34327,52314:34328,52315:34329,52316:34330,52317:34331,52318:34332,52319:34333,52320:34334,52321:34335,52322:34336,52323:34337,52324:34338,52325:34339,52326:34340,52327:34341,52328:34342,52329:34344,52330:34346,52331:34347,52332:34348,52333:34349,52334:34350,52335:34351,52336:34352,52337:34353,52338:34354,52339:34355,52340:34356,52341:34357,52342:34358,52343:34359,52344:34361,52345:34362,52346:34363,52347:34365,52348:34366,52349:34367,52350:34368,52352:34369,52353:34370,52354:34371,52355:34372,52356:34373,52357:34374,52358:34375,52359:34376,52360:34377,52361:34378,52362:34379,52363:34380,52364:34386,52365:34387,52366:34389,52367:34390,52368:34391,52369:34392,52370:34393,52371:34395,52372:34396,52373:34397,52374:34399,52375:34400,52376:34401,52377:34403,52378:34404,52379:34405,52380:34406,52381:34407,52382:34408,52383:34409,52384:34410,52385:29549,52386:25374,52387:36427,52388:36367,52389:32974,52390:33492,52391:25260,52392:21488,52393:27888,52394:37214,52395:22826,52396:24577,52397:27760,52398:22349,52399:25674,52400:36138,52401:30251,52402:28393,52403:22363,52404:27264,52405:30192,52406:28525,52407:35885,52408:35848,52409:22374,52410:27631,52411:34962,52412:30899,52413:25506,52414:21497,52415:28845,52416:27748,52417:22616,52418:25642,52419:22530,52420:26848,52421:33179,52422:21776,52423:31958,52424:20504,52425:36538,52426:28108,52427:36255,52428:28907,52429:25487,52430:28059,52431:28372,52432:32486,52433:33796,52434:26691,52435:36867,52436:28120,52437:38518,52438:35752,52439:22871,52440:29305,52441:34276,52442:33150,52443:30140,52444:35466,52445:26799,52446:21076,52447:36386,52448:38161,52449:25552,52450:39064,52451:36420,52452:21884,52453:20307,52454:26367,52455:22159,52456:24789,52457:28053,52458:21059,52459:23625,52460:22825,52461:28155,52462:22635,52463:30000,52464:29980,52465:24684,52466:33300,52467:33094,52468:25361,52469:26465,52470:36834,52471:30522,52472:36339,52473:36148,52474:38081,52475:24086,52476:21381,52477:21548,52478:28867,52544:34413,52545:34415,52546:34416,52547:34418,52548:34419,52549:34420,52550:34421,52551:34422,52552:34423,52553:34424,52554:34435,52555:34436,52556:34437,52557:34438,52558:34439,52559:34440,52560:34441,52561:34446,52562:34447,52563:34448,52564:34449,52565:34450,52566:34452,52567:34454,52568:34455,52569:34456,52570:34457,52571:34458,52572:34459,52573:34462,52574:34463,52575:34464,52576:34465,52577:34466,52578:34469,52579:34470,52580:34475,52581:34477,52582:34478,52583:34482,52584:34483,52585:34487,52586:34488,52587:34489,52588:34491,52589:34492,52590:34493,52591:34494,52592:34495,52593:34497,52594:34498,52595:34499,52596:34501,52597:34504,52598:34508,52599:34509,52600:34514,52601:34515,52602:34517,52603:34518,52604:34519,52605:34522,52606:34524,52608:34525,52609:34528,52610:34529,52611:34530,52612:34531,52613:34533,52614:34534,52615:34535,52616:34536,52617:34538,52618:34539,52619:34540,52620:34543,52621:34549,52622:34550,52623:34551,52624:34554,52625:34555,52626:34556,52627:34557,52628:34559,52629:34561,52630:34564,52631:34565,52632:34566,52633:34571,52634:34572,52635:34574,52636:34575,52637:34576,52638:34577,52639:34580,52640:34582,52641:27712,52642:24311,52643:20572,52644:20141,52645:24237,52646:25402,52647:33351,52648:36890,52649:26704,52650:37230,52651:30643,52652:21516,52653:38108,52654:24420,52655:31461,52656:26742,52657:25413,52658:31570,52659:32479,52660:30171,52661:20599,52662:25237,52663:22836,52664:36879,52665:20984,52666:31171,52667:31361,52668:22270,52669:24466,52670:36884,52671:28034,52672:23648,52673:22303,52674:21520,52675:20820,52676:28237,52677:22242,52678:25512,52679:39059,52680:33151,52681:34581,52682:35114,52683:36864,52684:21534,52685:23663,52686:33216,52687:25302,52688:25176,52689:33073,52690:40501,52691:38464,52692:39534,52693:39548,52694:26925,52695:22949,52696:25299,52697:21822,52698:25366,52699:21703,52700:34521,52701:27964,52702:23043,52703:29926,52704:34972,52705:27498,52706:22806,52707:35916,52708:24367,52709:28286,52710:29609,52711:39037,52712:20024,52713:28919,52714:23436,52715:30871,52716:25405,52717:26202,52718:30358,52719:24779,52720:23451,52721:23113,52722:19975,52723:33109,52724:27754,52725:29579,52726:20129,52727:26505,52728:32593,52729:24448,52730:26106,52731:26395,52732:24536,52733:22916,52734:23041,52800:34585,52801:34587,52802:34589,52803:34591,52804:34592,52805:34596,52806:34598,52807:34599,52808:34600,52809:34602,52810:34603,52811:34604,52812:34605,52813:34607,52814:34608,52815:34610,52816:34611,52817:34613,52818:34614,52819:34616,52820:34617,52821:34618,52822:34620,52823:34621,52824:34624,52825:34625,52826:34626,52827:34627,52828:34628,52829:34629,52830:34630,52831:34634,52832:34635,52833:34637,52834:34639,52835:34640,52836:34641,52837:34642,52838:34644,52839:34645,52840:34646,52841:34648,52842:34650,52843:34651,52844:34652,52845:34653,52846:34654,52847:34655,52848:34657,52849:34658,52850:34662,52851:34663,52852:34664,52853:34665,52854:34666,52855:34667,52856:34668,52857:34669,52858:34671,52859:34673,52860:34674,52861:34675,52862:34677,52864:34679,52865:34680,52866:34681,52867:34682,52868:34687,52869:34688,52870:34689,52871:34692,52872:34694,52873:34695,52874:34697,52875:34698,52876:34700,52877:34702,52878:34703,52879:34704,52880:34705,52881:34706,52882:34708,52883:34709,52884:34710,52885:34712,52886:34713,52887:34714,52888:34715,52889:34716,52890:34717,52891:34718,52892:34720,52893:34721,52894:34722,52895:34723,52896:34724,52897:24013,52898:24494,52899:21361,52900:38886,52901:36829,52902:26693,52903:22260,52904:21807,52905:24799,52906:20026,52907:28493,52908:32500,52909:33479,52910:33806,52911:22996,52912:20255,52913:20266,52914:23614,52915:32428,52916:26410,52917:34074,52918:21619,52919:30031,52920:32963,52921:21890,52922:39759,52923:20301,52924:28205,52925:35859,52926:23561,52927:24944,52928:21355,52929:30239,52930:28201,52931:34442,52932:25991,52933:38395,52934:32441,52935:21563,52936:31283,52937:32010,52938:38382,52939:21985,52940:32705,52941:29934,52942:25373,52943:34583,52944:28065,52945:31389,52946:25105,52947:26017,52948:21351,52949:25569,52950:27779,52951:24043,52952:21596,52953:38056,52954:20044,52955:27745,52956:35820,52957:23627,52958:26080,52959:33436,52960:26791,52961:21566,52962:21556,52963:27595,52964:27494,52965:20116,52966:25410,52967:21320,52968:33310,52969:20237,52970:20398,52971:22366,52972:25098,52973:38654,52974:26212,52975:29289,52976:21247,52977:21153,52978:24735,52979:35823,52980:26132,52981:29081,52982:26512,52983:35199,52984:30802,52985:30717,52986:26224,52987:22075,52988:21560,52989:38177,52990:29306,53056:34725,53057:34726,53058:34727,53059:34729,53060:34730,53061:34734,53062:34736,53063:34737,53064:34738,53065:34740,53066:34742,53067:34743,53068:34744,53069:34745,53070:34747,53071:34748,53072:34750,53073:34751,53074:34753,53075:34754,53076:34755,53077:34756,53078:34757,53079:34759,53080:34760,53081:34761,53082:34764,53083:34765,53084:34766,53085:34767,53086:34768,53087:34772,53088:34773,53089:34774,53090:34775,53091:34776,53092:34777,53093:34778,53094:34780,53095:34781,53096:34782,53097:34783,53098:34785,53099:34786,53100:34787,53101:34788,53102:34790,53103:34791,53104:34792,53105:34793,53106:34795,53107:34796,53108:34797,53109:34799,53110:34800,53111:34801,53112:34802,53113:34803,53114:34804,53115:34805,53116:34806,53117:34807,53118:34808,53120:34810,53121:34811,53122:34812,53123:34813,53124:34815,53125:34816,53126:34817,53127:34818,53128:34820,53129:34821,53130:34822,53131:34823,53132:34824,53133:34825,53134:34827,53135:34828,53136:34829,53137:34830,53138:34831,53139:34832,53140:34833,53141:34834,53142:34836,53143:34839,53144:34840,53145:34841,53146:34842,53147:34844,53148:34845,53149:34846,53150:34847,53151:34848,53152:34851,53153:31232,53154:24687,53155:24076,53156:24713,53157:33181,53158:22805,53159:24796,53160:29060,53161:28911,53162:28330,53163:27728,53164:29312,53165:27268,53166:34989,53167:24109,53168:20064,53169:23219,53170:21916,53171:38115,53172:27927,53173:31995,53174:38553,53175:25103,53176:32454,53177:30606,53178:34430,53179:21283,53180:38686,53181:36758,53182:26247,53183:23777,53184:20384,53185:29421,53186:19979,53187:21414,53188:22799,53189:21523,53190:25472,53191:38184,53192:20808,53193:20185,53194:40092,53195:32420,53196:21688,53197:36132,53198:34900,53199:33335,53200:38386,53201:28046,53202:24358,53203:23244,53204:26174,53205:38505,53206:29616,53207:29486,53208:21439,53209:33146,53210:39301,53211:32673,53212:23466,53213:38519,53214:38480,53215:32447,53216:30456,53217:21410,53218:38262,53219:39321,53220:31665,53221:35140,53222:28248,53223:20065,53224:32724,53225:31077,53226:35814,53227:24819,53228:21709,53229:20139,53230:39033,53231:24055,53232:27233,53233:20687,53234:21521,53235:35937,53236:33831,53237:30813,53238:38660,53239:21066,53240:21742,53241:22179,53242:38144,53243:28040,53244:23477,53245:28102,53246:26195,53312:34852,53313:34853,53314:34854,53315:34855,53316:34856,53317:34857,53318:34858,53319:34859,53320:34860,53321:34861,53322:34862,53323:34863,53324:34864,53325:34865,53326:34867,53327:34868,53328:34869,53329:34870,53330:34871,53331:34872,53332:34874,53333:34875,53334:34877,53335:34878,53336:34879,53337:34881,53338:34882,53339:34883,53340:34886,53341:34887,53342:34888,53343:34889,53344:34890,53345:34891,53346:34894,53347:34895,53348:34896,53349:34897,53350:34898,53351:34899,53352:34901,53353:34902,53354:34904,53355:34906,53356:34907,53357:34908,53358:34909,53359:34910,53360:34911,53361:34912,53362:34918,53363:34919,53364:34922,53365:34925,53366:34927,53367:34929,53368:34931,53369:34932,53370:34933,53371:34934,53372:34936,53373:34937,53374:34938,53376:34939,53377:34940,53378:34944,53379:34947,53380:34950,53381:34951,53382:34953,53383:34954,53384:34956,53385:34958,53386:34959,53387:34960,53388:34961,53389:34963,53390:34964,53391:34965,53392:34967,53393:34968,53394:34969,53395:34970,53396:34971,53397:34973,53398:34974,53399:34975,53400:34976,53401:34977,53402:34979,53403:34981,53404:34982,53405:34983,53406:34984,53407:34985,53408:34986,53409:23567,53410:23389,53411:26657,53412:32918,53413:21880,53414:31505,53415:25928,53416:26964,53417:20123,53418:27463,53419:34638,53420:38795,53421:21327,53422:25375,53423:25658,53424:37034,53425:26012,53426:32961,53427:35856,53428:20889,53429:26800,53430:21368,53431:34809,53432:25032,53433:27844,53434:27899,53435:35874,53436:23633,53437:34218,53438:33455,53439:38156,53440:27427,53441:36763,53442:26032,53443:24571,53444:24515,53445:20449,53446:34885,53447:26143,53448:33125,53449:29481,53450:24826,53451:20852,53452:21009,53453:22411,53454:24418,53455:37026,53456:34892,53457:37266,53458:24184,53459:26447,53460:24615,53461:22995,53462:20804,53463:20982,53464:33016,53465:21256,53466:27769,53467:38596,53468:29066,53469:20241,53470:20462,53471:32670,53472:26429,53473:21957,53474:38152,53475:31168,53476:34966,53477:32483,53478:22687,53479:25100,53480:38656,53481:34394,53482:22040,53483:39035,53484:24464,53485:35768,53486:33988,53487:37207,53488:21465,53489:26093,53490:24207,53491:30044,53492:24676,53493:32110,53494:23167,53495:32490,53496:32493,53497:36713,53498:21927,53499:23459,53500:24748,53501:26059,53502:29572,53568:34988,53569:34990,53570:34991,53571:34992,53572:34994,53573:34995,53574:34996,53575:34997,53576:34998,53577:35000,53578:35001,53579:35002,53580:35003,53581:35005,53582:35006,53583:35007,53584:35008,53585:35011,53586:35012,53587:35015,53588:35016,53589:35018,53590:35019,53591:35020,53592:35021,53593:35023,53594:35024,53595:35025,53596:35027,53597:35030,53598:35031,53599:35034,53600:35035,53601:35036,53602:35037,53603:35038,53604:35040,53605:35041,53606:35046,53607:35047,53608:35049,53609:35050,53610:35051,53611:35052,53612:35053,53613:35054,53614:35055,53615:35058,53616:35061,53617:35062,53618:35063,53619:35066,53620:35067,53621:35069,53622:35071,53623:35072,53624:35073,53625:35075,53626:35076,53627:35077,53628:35078,53629:35079,53630:35080,53632:35081,53633:35083,53634:35084,53635:35085,53636:35086,53637:35087,53638:35089,53639:35092,53640:35093,53641:35094,53642:35095,53643:35096,53644:35100,53645:35101,53646:35102,53647:35103,53648:35104,53649:35106,53650:35107,53651:35108,53652:35110,53653:35111,53654:35112,53655:35113,53656:35116,53657:35117,53658:35118,53659:35119,53660:35121,53661:35122,53662:35123,53663:35125,53664:35127,53665:36873,53666:30307,53667:30505,53668:32474,53669:38772,53670:34203,53671:23398,53672:31348,53673:38634,53674:34880,53675:21195,53676:29071,53677:24490,53678:26092,53679:35810,53680:23547,53681:39535,53682:24033,53683:27529,53684:27739,53685:35757,53686:35759,53687:36874,53688:36805,53689:21387,53690:25276,53691:40486,53692:40493,53693:21568,53694:20011,53695:33469,53696:29273,53697:34460,53698:23830,53699:34905,53700:28079,53701:38597,53702:21713,53703:20122,53704:35766,53705:28937,53706:21693,53707:38409,53708:28895,53709:28153,53710:30416,53711:20005,53712:30740,53713:34578,53714:23721,53715:24310,53716:35328,53717:39068,53718:38414,53719:28814,53720:27839,53721:22852,53722:25513,53723:30524,53724:34893,53725:28436,53726:33395,53727:22576,53728:29141,53729:21388,53730:30746,53731:38593,53732:21761,53733:24422,53734:28976,53735:23476,53736:35866,53737:39564,53738:27523,53739:22830,53740:40495,53741:31207,53742:26472,53743:25196,53744:20335,53745:30113,53746:32650,53747:27915,53748:38451,53749:27687,53750:20208,53751:30162,53752:20859,53753:26679,53754:28478,53755:36992,53756:33136,53757:22934,53758:29814,53824:35128,53825:35129,53826:35130,53827:35131,53828:35132,53829:35133,53830:35134,53831:35135,53832:35136,53833:35138,53834:35139,53835:35141,53836:35142,53837:35143,53838:35144,53839:35145,53840:35146,53841:35147,53842:35148,53843:35149,53844:35150,53845:35151,53846:35152,53847:35153,53848:35154,53849:35155,53850:35156,53851:35157,53852:35158,53853:35159,53854:35160,53855:35161,53856:35162,53857:35163,53858:35164,53859:35165,53860:35168,53861:35169,53862:35170,53863:35171,53864:35172,53865:35173,53866:35175,53867:35176,53868:35177,53869:35178,53870:35179,53871:35180,53872:35181,53873:35182,53874:35183,53875:35184,53876:35185,53877:35186,53878:35187,53879:35188,53880:35189,53881:35190,53882:35191,53883:35192,53884:35193,53885:35194,53886:35196,53888:35197,53889:35198,53890:35200,53891:35202,53892:35204,53893:35205,53894:35207,53895:35208,53896:35209,53897:35210,53898:35211,53899:35212,53900:35213,53901:35214,53902:35215,53903:35216,53904:35217,53905:35218,53906:35219,53907:35220,53908:35221,53909:35222,53910:35223,53911:35224,53912:35225,53913:35226,53914:35227,53915:35228,53916:35229,53917:35230,53918:35231,53919:35232,53920:35233,53921:25671,53922:23591,53923:36965,53924:31377,53925:35875,53926:23002,53927:21676,53928:33280,53929:33647,53930:35201,53931:32768,53932:26928,53933:22094,53934:32822,53935:29239,53936:37326,53937:20918,53938:20063,53939:39029,53940:25494,53941:19994,53942:21494,53943:26355,53944:33099,53945:22812,53946:28082,53947:19968,53948:22777,53949:21307,53950:25558,53951:38129,53952:20381,53953:20234,53954:34915,53955:39056,53956:22839,53957:36951,53958:31227,53959:20202,53960:33008,53961:30097,53962:27778,53963:23452,53964:23016,53965:24413,53966:26885,53967:34433,53968:20506,53969:24050,53970:20057,53971:30691,53972:20197,53973:33402,53974:25233,53975:26131,53976:37009,53977:23673,53978:20159,53979:24441,53980:33222,53981:36920,53982:32900,53983:30123,53984:20134,53985:35028,53986:24847,53987:27589,53988:24518,53989:20041,53990:30410,53991:28322,53992:35811,53993:35758,53994:35850,53995:35793,53996:24322,53997:32764,53998:32716,53999:32462,54000:33589,54001:33643,54002:22240,54003:27575,54004:38899,54005:38452,54006:23035,54007:21535,54008:38134,54009:28139,54010:23493,54011:39278,54012:23609,54013:24341,54014:38544,54080:35234,54081:35235,54082:35236,54083:35237,54084:35238,54085:35239,54086:35240,54087:35241,54088:35242,54089:35243,54090:35244,54091:35245,54092:35246,54093:35247,54094:35248,54095:35249,54096:35250,54097:35251,54098:35252,54099:35253,54100:35254,54101:35255,54102:35256,54103:35257,54104:35258,54105:35259,54106:35260,54107:35261,54108:35262,54109:35263,54110:35264,54111:35267,54112:35277,54113:35283,54114:35284,54115:35285,54116:35287,54117:35288,54118:35289,54119:35291,54120:35293,54121:35295,54122:35296,54123:35297,54124:35298,54125:35300,54126:35303,54127:35304,54128:35305,54129:35306,54130:35308,54131:35309,54132:35310,54133:35312,54134:35313,54135:35314,54136:35316,54137:35317,54138:35318,54139:35319,54140:35320,54141:35321,54142:35322,54144:35323,54145:35324,54146:35325,54147:35326,54148:35327,54149:35329,54150:35330,54151:35331,54152:35332,54153:35333,54154:35334,54155:35336,54156:35337,54157:35338,54158:35339,54159:35340,54160:35341,54161:35342,54162:35343,54163:35344,54164:35345,54165:35346,54166:35347,54167:35348,54168:35349,54169:35350,54170:35351,54171:35352,54172:35353,54173:35354,54174:35355,54175:35356,54176:35357,54177:21360,54178:33521,54179:27185,54180:23156,54181:40560,54182:24212,54183:32552,54184:33721,54185:33828,54186:33829,54187:33639,54188:34631,54189:36814,54190:36194,54191:30408,54192:24433,54193:39062,54194:30828,54195:26144,54196:21727,54197:25317,54198:20323,54199:33219,54200:30152,54201:24248,54202:38605,54203:36362,54204:34553,54205:21647,54206:27891,54207:28044,54208:27704,54209:24703,54210:21191,54211:29992,54212:24189,54213:20248,54214:24736,54215:24551,54216:23588,54217:30001,54218:37038,54219:38080,54220:29369,54221:27833,54222:28216,54223:37193,54224:26377,54225:21451,54226:21491,54227:20305,54228:37321,54229:35825,54230:21448,54231:24188,54232:36802,54233:28132,54234:20110,54235:30402,54236:27014,54237:34398,54238:24858,54239:33286,54240:20313,54241:20446,54242:36926,54243:40060,54244:24841,54245:28189,54246:28180,54247:38533,54248:20104,54249:23089,54250:38632,54251:19982,54252:23679,54253:31161,54254:23431,54255:35821,54256:32701,54257:29577,54258:22495,54259:33419,54260:37057,54261:21505,54262:36935,54263:21947,54264:23786,54265:24481,54266:24840,54267:27442,54268:29425,54269:32946,54270:35465,54336:35358,54337:35359,54338:35360,54339:35361,54340:35362,54341:35363,54342:35364,54343:35365,54344:35366,54345:35367,54346:35368,54347:35369,54348:35370,54349:35371,54350:35372,54351:35373,54352:35374,54353:35375,54354:35376,54355:35377,54356:35378,54357:35379,54358:35380,54359:35381,54360:35382,54361:35383,54362:35384,54363:35385,54364:35386,54365:35387,54366:35388,54367:35389,54368:35391,54369:35392,54370:35393,54371:35394,54372:35395,54373:35396,54374:35397,54375:35398,54376:35399,54377:35401,54378:35402,54379:35403,54380:35404,54381:35405,54382:35406,54383:35407,54384:35408,54385:35409,54386:35410,54387:35411,54388:35412,54389:35413,54390:35414,54391:35415,54392:35416,54393:35417,54394:35418,54395:35419,54396:35420,54397:35421,54398:35422,54400:35423,54401:35424,54402:35425,54403:35426,54404:35427,54405:35428,54406:35429,54407:35430,54408:35431,54409:35432,54410:35433,54411:35434,54412:35435,54413:35436,54414:35437,54415:35438,54416:35439,54417:35440,54418:35441,54419:35442,54420:35443,54421:35444,54422:35445,54423:35446,54424:35447,54425:35448,54426:35450,54427:35451,54428:35452,54429:35453,54430:35454,54431:35455,54432:35456,54433:28020,54434:23507,54435:35029,54436:39044,54437:35947,54438:39533,54439:40499,54440:28170,54441:20900,54442:20803,54443:22435,54444:34945,54445:21407,54446:25588,54447:36757,54448:22253,54449:21592,54450:22278,54451:29503,54452:28304,54453:32536,54454:36828,54455:33489,54456:24895,54457:24616,54458:38498,54459:26352,54460:32422,54461:36234,54462:36291,54463:38053,54464:23731,54465:31908,54466:26376,54467:24742,54468:38405,54469:32792,54470:20113,54471:37095,54472:21248,54473:38504,54474:20801,54475:36816,54476:34164,54477:37213,54478:26197,54479:38901,54480:23381,54481:21277,54482:30776,54483:26434,54484:26685,54485:21705,54486:28798,54487:23472,54488:36733,54489:20877,54490:22312,54491:21681,54492:25874,54493:26242,54494:36190,54495:36163,54496:33039,54497:33900,54498:36973,54499:31967,54500:20991,54501:34299,54502:26531,54503:26089,54504:28577,54505:34468,54506:36481,54507:22122,54508:36896,54509:30338,54510:28790,54511:29157,54512:36131,54513:25321,54514:21017,54515:27901,54516:36156,54517:24590,54518:22686,54519:24974,54520:26366,54521:36192,54522:25166,54523:21939,54524:28195,54525:26413,54526:36711,54592:35457,54593:35458,54594:35459,54595:35460,54596:35461,54597:35462,54598:35463,54599:35464,54600:35467,54601:35468,54602:35469,54603:35470,54604:35471,54605:35472,54606:35473,54607:35474,54608:35476,54609:35477,54610:35478,54611:35479,54612:35480,54613:35481,54614:35482,54615:35483,54616:35484,54617:35485,54618:35486,54619:35487,54620:35488,54621:35489,54622:35490,54623:35491,54624:35492,54625:35493,54626:35494,54627:35495,54628:35496,54629:35497,54630:35498,54631:35499,54632:35500,54633:35501,54634:35502,54635:35503,54636:35504,54637:35505,54638:35506,54639:35507,54640:35508,54641:35509,54642:35510,54643:35511,54644:35512,54645:35513,54646:35514,54647:35515,54648:35516,54649:35517,54650:35518,54651:35519,54652:35520,54653:35521,54654:35522,54656:35523,54657:35524,54658:35525,54659:35526,54660:35527,54661:35528,54662:35529,54663:35530,54664:35531,54665:35532,54666:35533,54667:35534,54668:35535,54669:35536,54670:35537,54671:35538,54672:35539,54673:35540,54674:35541,54675:35542,54676:35543,54677:35544,54678:35545,54679:35546,54680:35547,54681:35548,54682:35549,54683:35550,54684:35551,54685:35552,54686:35553,54687:35554,54688:35555,54689:38113,54690:38392,54691:30504,54692:26629,54693:27048,54694:21643,54695:20045,54696:28856,54697:35784,54698:25688,54699:25995,54700:23429,54701:31364,54702:20538,54703:23528,54704:30651,54705:27617,54706:35449,54707:31896,54708:27838,54709:30415,54710:26025,54711:36759,54712:23853,54713:23637,54714:34360,54715:26632,54716:21344,54717:25112,54718:31449,54719:28251,54720:32509,54721:27167,54722:31456,54723:24432,54724:28467,54725:24352,54726:25484,54727:28072,54728:26454,54729:19976,54730:24080,54731:36134,54732:20183,54733:32960,54734:30260,54735:38556,54736:25307,54737:26157,54738:25214,54739:27836,54740:36213,54741:29031,54742:32617,54743:20806,54744:32903,54745:21484,54746:36974,54747:25240,54748:21746,54749:34544,54750:36761,54751:32773,54752:38167,54753:34071,54754:36825,54755:27993,54756:29645,54757:26015,54758:30495,54759:29956,54760:30759,54761:33275,54762:36126,54763:38024,54764:20390,54765:26517,54766:30137,54767:35786,54768:38663,54769:25391,54770:38215,54771:38453,54772:33976,54773:25379,54774:30529,54775:24449,54776:29424,54777:20105,54778:24596,54779:25972,54780:25327,54781:27491,54782:25919,54848:35556,54849:35557,54850:35558,54851:35559,54852:35560,54853:35561,54854:35562,54855:35563,54856:35564,54857:35565,54858:35566,54859:35567,54860:35568,54861:35569,54862:35570,54863:35571,54864:35572,54865:35573,54866:35574,54867:35575,54868:35576,54869:35577,54870:35578,54871:35579,54872:35580,54873:35581,54874:35582,54875:35583,54876:35584,54877:35585,54878:35586,54879:35587,54880:35588,54881:35589,54882:35590,54883:35592,54884:35593,54885:35594,54886:35595,54887:35596,54888:35597,54889:35598,54890:35599,54891:35600,54892:35601,54893:35602,54894:35603,54895:35604,54896:35605,54897:35606,54898:35607,54899:35608,54900:35609,54901:35610,54902:35611,54903:35612,54904:35613,54905:35614,54906:35615,54907:35616,54908:35617,54909:35618,54910:35619,54912:35620,54913:35621,54914:35623,54915:35624,54916:35625,54917:35626,54918:35627,54919:35628,54920:35629,54921:35630,54922:35631,54923:35632,54924:35633,54925:35634,54926:35635,54927:35636,54928:35637,54929:35638,54930:35639,54931:35640,54932:35641,54933:35642,54934:35643,54935:35644,54936:35645,54937:35646,54938:35647,54939:35648,54940:35649,54941:35650,54942:35651,54943:35652,54944:35653,54945:24103,54946:30151,54947:37073,54948:35777,54949:33437,54950:26525,54951:25903,54952:21553,54953:34584,54954:30693,54955:32930,54956:33026,54957:27713,54958:20043,54959:32455,54960:32844,54961:30452,54962:26893,54963:27542,54964:25191,54965:20540,54966:20356,54967:22336,54968:25351,54969:27490,54970:36286,54971:21482,54972:26088,54973:32440,54974:24535,54975:25370,54976:25527,54977:33267,54978:33268,54979:32622,54980:24092,54981:23769,54982:21046,54983:26234,54984:31209,54985:31258,54986:36136,54987:28825,54988:30164,54989:28382,54990:27835,54991:31378,54992:20013,54993:30405,54994:24544,54995:38047,54996:34935,54997:32456,54998:31181,54999:32959,55000:37325,55001:20210,55002:20247,55003:33311,55004:21608,55005:24030,55006:27954,55007:35788,55008:31909,55009:36724,55010:32920,55011:24090,55012:21650,55013:30385,55014:23449,55015:26172,55016:39588,55017:29664,55018:26666,55019:34523,55020:26417,55021:29482,55022:35832,55023:35803,55024:36880,55025:31481,55026:28891,55027:29038,55028:25284,55029:30633,55030:22065,55031:20027,55032:33879,55033:26609,55034:21161,55035:34496,55036:36142,55037:38136,55038:31569,55104:35654,55105:35655,55106:35656,55107:35657,55108:35658,55109:35659,55110:35660,55111:35661,55112:35662,55113:35663,55114:35664,55115:35665,55116:35666,55117:35667,55118:35668,55119:35669,55120:35670,55121:35671,55122:35672,55123:35673,55124:35674,55125:35675,55126:35676,55127:35677,55128:35678,55129:35679,55130:35680,55131:35681,55132:35682,55133:35683,55134:35684,55135:35685,55136:35687,55137:35688,55138:35689,55139:35690,55140:35691,55141:35693,55142:35694,55143:35695,55144:35696,55145:35697,55146:35698,55147:35699,55148:35700,55149:35701,55150:35702,55151:35703,55152:35704,55153:35705,55154:35706,55155:35707,55156:35708,55157:35709,55158:35710,55159:35711,55160:35712,55161:35713,55162:35714,55163:35715,55164:35716,55165:35717,55166:35718,55168:35719,55169:35720,55170:35721,55171:35722,55172:35723,55173:35724,55174:35725,55175:35726,55176:35727,55177:35728,55178:35729,55179:35730,55180:35731,55181:35732,55182:35733,55183:35734,55184:35735,55185:35736,55186:35737,55187:35738,55188:35739,55189:35740,55190:35741,55191:35742,55192:35743,55193:35756,55194:35761,55195:35771,55196:35783,55197:35792,55198:35818,55199:35849,55200:35870,55201:20303,55202:27880,55203:31069,55204:39547,55205:25235,55206:29226,55207:25341,55208:19987,55209:30742,55210:36716,55211:25776,55212:36186,55213:31686,55214:26729,55215:24196,55216:35013,55217:22918,55218:25758,55219:22766,55220:29366,55221:26894,55222:38181,55223:36861,55224:36184,55225:22368,55226:32512,55227:35846,55228:20934,55229:25417,55230:25305,55231:21331,55232:26700,55233:29730,55234:33537,55235:37196,55236:21828,55237:30528,55238:28796,55239:27978,55240:20857,55241:21672,55242:36164,55243:23039,55244:28363,55245:28100,55246:23388,55247:32043,55248:20180,55249:31869,55250:28371,55251:23376,55252:33258,55253:28173,55254:23383,55255:39683,55256:26837,55257:36394,55258:23447,55259:32508,55260:24635,55261:32437,55262:37049,55263:36208,55264:22863,55265:25549,55266:31199,55267:36275,55268:21330,55269:26063,55270:31062,55271:35781,55272:38459,55273:32452,55274:38075,55275:32386,55276:22068,55277:37257,55278:26368,55279:32618,55280:23562,55281:36981,55282:26152,55283:24038,55284:20304,55285:26590,55286:20570,55287:20316,55288:22352,55289:24231,55290:59408,55291:59409,55292:59410,55293:59411,55294:59412,55360:35896,55361:35897,55362:35898,55363:35899,55364:35900,55365:35901,55366:35902,55367:35903,55368:35904,55369:35906,55370:35907,55371:35908,55372:35909,55373:35912,55374:35914,55375:35915,55376:35917,55377:35918,55378:35919,55379:35920,55380:35921,55381:35922,55382:35923,55383:35924,55384:35926,55385:35927,55386:35928,55387:35929,55388:35931,55389:35932,55390:35933,55391:35934,55392:35935,55393:35936,55394:35939,55395:35940,55396:35941,55397:35942,55398:35943,55399:35944,55400:35945,55401:35948,55402:35949,55403:35950,55404:35951,55405:35952,55406:35953,55407:35954,55408:35956,55409:35957,55410:35958,55411:35959,55412:35963,55413:35964,55414:35965,55415:35966,55416:35967,55417:35968,55418:35969,55419:35971,55420:35972,55421:35974,55422:35975,55424:35976,55425:35979,55426:35981,55427:35982,55428:35983,55429:35984,55430:35985,55431:35986,55432:35987,55433:35989,55434:35990,55435:35991,55436:35993,55437:35994,55438:35995,55439:35996,55440:35997,55441:35998,55442:35999,55443:36000,55444:36001,55445:36002,55446:36003,55447:36004,55448:36005,55449:36006,55450:36007,55451:36008,55452:36009,55453:36010,55454:36011,55455:36012,55456:36013,55457:20109,55458:19980,55459:20800,55460:19984,55461:24319,55462:21317,55463:19989,55464:20120,55465:19998,55466:39730,55467:23404,55468:22121,55469:20008,55470:31162,55471:20031,55472:21269,55473:20039,55474:22829,55475:29243,55476:21358,55477:27664,55478:22239,55479:32996,55480:39319,55481:27603,55482:30590,55483:40727,55484:20022,55485:20127,55486:40720,55487:20060,55488:20073,55489:20115,55490:33416,55491:23387,55492:21868,55493:22031,55494:20164,55495:21389,55496:21405,55497:21411,55498:21413,55499:21422,55500:38757,55501:36189,55502:21274,55503:21493,55504:21286,55505:21294,55506:21310,55507:36188,55508:21350,55509:21347,55510:20994,55511:21000,55512:21006,55513:21037,55514:21043,55515:21055,55516:21056,55517:21068,55518:21086,55519:21089,55520:21084,55521:33967,55522:21117,55523:21122,55524:21121,55525:21136,55526:21139,55527:20866,55528:32596,55529:20155,55530:20163,55531:20169,55532:20162,55533:20200,55534:20193,55535:20203,55536:20190,55537:20251,55538:20211,55539:20258,55540:20324,55541:20213,55542:20261,55543:20263,55544:20233,55545:20267,55546:20318,55547:20327,55548:25912,55549:20314,55550:20317,55616:36014,55617:36015,55618:36016,55619:36017,55620:36018,55621:36019,55622:36020,55623:36021,55624:36022,55625:36023,55626:36024,55627:36025,55628:36026,55629:36027,55630:36028,55631:36029,55632:36030,55633:36031,55634:36032,55635:36033,55636:36034,55637:36035,55638:36036,55639:36037,55640:36038,55641:36039,55642:36040,55643:36041,55644:36042,55645:36043,55646:36044,55647:36045,55648:36046,55649:36047,55650:36048,55651:36049,55652:36050,55653:36051,55654:36052,55655:36053,55656:36054,55657:36055,55658:36056,55659:36057,55660:36058,55661:36059,55662:36060,55663:36061,55664:36062,55665:36063,55666:36064,55667:36065,55668:36066,55669:36067,55670:36068,55671:36069,55672:36070,55673:36071,55674:36072,55675:36073,55676:36074,55677:36075,55678:36076,55680:36077,55681:36078,55682:36079,55683:36080,55684:36081,55685:36082,55686:36083,55687:36084,55688:36085,55689:36086,55690:36087,55691:36088,55692:36089,55693:36090,55694:36091,55695:36092,55696:36093,55697:36094,55698:36095,55699:36096,55700:36097,55701:36098,55702:36099,55703:36100,55704:36101,55705:36102,55706:36103,55707:36104,55708:36105,55709:36106,55710:36107,55711:36108,55712:36109,55713:20319,55714:20311,55715:20274,55716:20285,55717:20342,55718:20340,55719:20369,55720:20361,55721:20355,55722:20367,55723:20350,55724:20347,55725:20394,55726:20348,55727:20396,55728:20372,55729:20454,55730:20456,55731:20458,55732:20421,55733:20442,55734:20451,55735:20444,55736:20433,55737:20447,55738:20472,55739:20521,55740:20556,55741:20467,55742:20524,55743:20495,55744:20526,55745:20525,55746:20478,55747:20508,55748:20492,55749:20517,55750:20520,55751:20606,55752:20547,55753:20565,55754:20552,55755:20558,55756:20588,55757:20603,55758:20645,55759:20647,55760:20649,55761:20666,55762:20694,55763:20742,55764:20717,55765:20716,55766:20710,55767:20718,55768:20743,55769:20747,55770:20189,55771:27709,55772:20312,55773:20325,55774:20430,55775:40864,55776:27718,55777:31860,55778:20846,55779:24061,55780:40649,55781:39320,55782:20865,55783:22804,55784:21241,55785:21261,55786:35335,55787:21264,55788:20971,55789:22809,55790:20821,55791:20128,55792:20822,55793:20147,55794:34926,55795:34980,55796:20149,55797:33044,55798:35026,55799:31104,55800:23348,55801:34819,55802:32696,55803:20907,55804:20913,55805:20925,55806:20924,55872:36110,55873:36111,55874:36112,55875:36113,55876:36114,55877:36115,55878:36116,55879:36117,55880:36118,55881:36119,55882:36120,55883:36121,55884:36122,55885:36123,55886:36124,55887:36128,55888:36177,55889:36178,55890:36183,55891:36191,55892:36197,55893:36200,55894:36201,55895:36202,55896:36204,55897:36206,55898:36207,55899:36209,55900:36210,55901:36216,55902:36217,55903:36218,55904:36219,55905:36220,55906:36221,55907:36222,55908:36223,55909:36224,55910:36226,55911:36227,55912:36230,55913:36231,55914:36232,55915:36233,55916:36236,55917:36237,55918:36238,55919:36239,55920:36240,55921:36242,55922:36243,55923:36245,55924:36246,55925:36247,55926:36248,55927:36249,55928:36250,55929:36251,55930:36252,55931:36253,55932:36254,55933:36256,55934:36257,55936:36258,55937:36260,55938:36261,55939:36262,55940:36263,55941:36264,55942:36265,55943:36266,55944:36267,55945:36268,55946:36269,55947:36270,55948:36271,55949:36272,55950:36274,55951:36278,55952:36279,55953:36281,55954:36283,55955:36285,55956:36288,55957:36289,55958:36290,55959:36293,55960:36295,55961:36296,55962:36297,55963:36298,55964:36301,55965:36304,55966:36306,55967:36307,55968:36308,55969:20935,55970:20886,55971:20898,55972:20901,55973:35744,55974:35750,55975:35751,55976:35754,55977:35764,55978:35765,55979:35767,55980:35778,55981:35779,55982:35787,55983:35791,55984:35790,55985:35794,55986:35795,55987:35796,55988:35798,55989:35800,55990:35801,55991:35804,55992:35807,55993:35808,55994:35812,55995:35816,55996:35817,55997:35822,55998:35824,55999:35827,56000:35830,56001:35833,56002:35836,56003:35839,56004:35840,56005:35842,56006:35844,56007:35847,56008:35852,56009:35855,56010:35857,56011:35858,56012:35860,56013:35861,56014:35862,56015:35865,56016:35867,56017:35864,56018:35869,56019:35871,56020:35872,56021:35873,56022:35877,56023:35879,56024:35882,56025:35883,56026:35886,56027:35887,56028:35890,56029:35891,56030:35893,56031:35894,56032:21353,56033:21370,56034:38429,56035:38434,56036:38433,56037:38449,56038:38442,56039:38461,56040:38460,56041:38466,56042:38473,56043:38484,56044:38495,56045:38503,56046:38508,56047:38514,56048:38516,56049:38536,56050:38541,56051:38551,56052:38576,56053:37015,56054:37019,56055:37021,56056:37017,56057:37036,56058:37025,56059:37044,56060:37043,56061:37046,56062:37050,56128:36309,56129:36312,56130:36313,56131:36316,56132:36320,56133:36321,56134:36322,56135:36325,56136:36326,56137:36327,56138:36329,56139:36333,56140:36334,56141:36336,56142:36337,56143:36338,56144:36340,56145:36342,56146:36348,56147:36350,56148:36351,56149:36352,56150:36353,56151:36354,56152:36355,56153:36356,56154:36358,56155:36359,56156:36360,56157:36363,56158:36365,56159:36366,56160:36368,56161:36369,56162:36370,56163:36371,56164:36373,56165:36374,56166:36375,56167:36376,56168:36377,56169:36378,56170:36379,56171:36380,56172:36384,56173:36385,56174:36388,56175:36389,56176:36390,56177:36391,56178:36392,56179:36395,56180:36397,56181:36400,56182:36402,56183:36403,56184:36404,56185:36406,56186:36407,56187:36408,56188:36411,56189:36412,56190:36414,56192:36415,56193:36419,56194:36421,56195:36422,56196:36428,56197:36429,56198:36430,56199:36431,56200:36432,56201:36435,56202:36436,56203:36437,56204:36438,56205:36439,56206:36440,56207:36442,56208:36443,56209:36444,56210:36445,56211:36446,56212:36447,56213:36448,56214:36449,56215:36450,56216:36451,56217:36452,56218:36453,56219:36455,56220:36456,56221:36458,56222:36459,56223:36462,56224:36465,56225:37048,56226:37040,56227:37071,56228:37061,56229:37054,56230:37072,56231:37060,56232:37063,56233:37075,56234:37094,56235:37090,56236:37084,56237:37079,56238:37083,56239:37099,56240:37103,56241:37118,56242:37124,56243:37154,56244:37150,56245:37155,56246:37169,56247:37167,56248:37177,56249:37187,56250:37190,56251:21005,56252:22850,56253:21154,56254:21164,56255:21165,56256:21182,56257:21759,56258:21200,56259:21206,56260:21232,56261:21471,56262:29166,56263:30669,56264:24308,56265:20981,56266:20988,56267:39727,56268:21430,56269:24321,56270:30042,56271:24047,56272:22348,56273:22441,56274:22433,56275:22654,56276:22716,56277:22725,56278:22737,56279:22313,56280:22316,56281:22314,56282:22323,56283:22329,56284:22318,56285:22319,56286:22364,56287:22331,56288:22338,56289:22377,56290:22405,56291:22379,56292:22406,56293:22396,56294:22395,56295:22376,56296:22381,56297:22390,56298:22387,56299:22445,56300:22436,56301:22412,56302:22450,56303:22479,56304:22439,56305:22452,56306:22419,56307:22432,56308:22485,56309:22488,56310:22490,56311:22489,56312:22482,56313:22456,56314:22516,56315:22511,56316:22520,56317:22500,56318:22493,56384:36467,56385:36469,56386:36471,56387:36472,56388:36473,56389:36474,56390:36475,56391:36477,56392:36478,56393:36480,56394:36482,56395:36483,56396:36484,56397:36486,56398:36488,56399:36489,56400:36490,56401:36491,56402:36492,56403:36493,56404:36494,56405:36497,56406:36498,56407:36499,56408:36501,56409:36502,56410:36503,56411:36504,56412:36505,56413:36506,56414:36507,56415:36509,56416:36511,56417:36512,56418:36513,56419:36514,56420:36515,56421:36516,56422:36517,56423:36518,56424:36519,56425:36520,56426:36521,56427:36522,56428:36525,56429:36526,56430:36528,56431:36529,56432:36531,56433:36532,56434:36533,56435:36534,56436:36535,56437:36536,56438:36537,56439:36539,56440:36540,56441:36541,56442:36542,56443:36543,56444:36544,56445:36545,56446:36546,56448:36547,56449:36548,56450:36549,56451:36550,56452:36551,56453:36552,56454:36553,56455:36554,56456:36555,56457:36556,56458:36557,56459:36559,56460:36560,56461:36561,56462:36562,56463:36563,56464:36564,56465:36565,56466:36566,56467:36567,56468:36568,56469:36569,56470:36570,56471:36571,56472:36572,56473:36573,56474:36574,56475:36575,56476:36576,56477:36577,56478:36578,56479:36579,56480:36580,56481:22539,56482:22541,56483:22525,56484:22509,56485:22528,56486:22558,56487:22553,56488:22596,56489:22560,56490:22629,56491:22636,56492:22657,56493:22665,56494:22682,56495:22656,56496:39336,56497:40729,56498:25087,56499:33401,56500:33405,56501:33407,56502:33423,56503:33418,56504:33448,56505:33412,56506:33422,56507:33425,56508:33431,56509:33433,56510:33451,56511:33464,56512:33470,56513:33456,56514:33480,56515:33482,56516:33507,56517:33432,56518:33463,56519:33454,56520:33483,56521:33484,56522:33473,56523:33449,56524:33460,56525:33441,56526:33450,56527:33439,56528:33476,56529:33486,56530:33444,56531:33505,56532:33545,56533:33527,56534:33508,56535:33551,56536:33543,56537:33500,56538:33524,56539:33490,56540:33496,56541:33548,56542:33531,56543:33491,56544:33553,56545:33562,56546:33542,56547:33556,56548:33557,56549:33504,56550:33493,56551:33564,56552:33617,56553:33627,56554:33628,56555:33544,56556:33682,56557:33596,56558:33588,56559:33585,56560:33691,56561:33630,56562:33583,56563:33615,56564:33607,56565:33603,56566:33631,56567:33600,56568:33559,56569:33632,56570:33581,56571:33594,56572:33587,56573:33638,56574:33637,56640:36581,56641:36582,56642:36583,56643:36584,56644:36585,56645:36586,56646:36587,56647:36588,56648:36589,56649:36590,56650:36591,56651:36592,56652:36593,56653:36594,56654:36595,56655:36596,56656:36597,56657:36598,56658:36599,56659:36600,56660:36601,56661:36602,56662:36603,56663:36604,56664:36605,56665:36606,56666:36607,56667:36608,56668:36609,56669:36610,56670:36611,56671:36612,56672:36613,56673:36614,56674:36615,56675:36616,56676:36617,56677:36618,56678:36619,56679:36620,56680:36621,56681:36622,56682:36623,56683:36624,56684:36625,56685:36626,56686:36627,56687:36628,56688:36629,56689:36630,56690:36631,56691:36632,56692:36633,56693:36634,56694:36635,56695:36636,56696:36637,56697:36638,56698:36639,56699:36640,56700:36641,56701:36642,56702:36643,56704:36644,56705:36645,56706:36646,56707:36647,56708:36648,56709:36649,56710:36650,56711:36651,56712:36652,56713:36653,56714:36654,56715:36655,56716:36656,56717:36657,56718:36658,56719:36659,56720:36660,56721:36661,56722:36662,56723:36663,56724:36664,56725:36665,56726:36666,56727:36667,56728:36668,56729:36669,56730:36670,56731:36671,56732:36672,56733:36673,56734:36674,56735:36675,56736:36676,56737:33640,56738:33563,56739:33641,56740:33644,56741:33642,56742:33645,56743:33646,56744:33712,56745:33656,56746:33715,56747:33716,56748:33696,56749:33706,56750:33683,56751:33692,56752:33669,56753:33660,56754:33718,56755:33705,56756:33661,56757:33720,56758:33659,56759:33688,56760:33694,56761:33704,56762:33722,56763:33724,56764:33729,56765:33793,56766:33765,56767:33752,56768:22535,56769:33816,56770:33803,56771:33757,56772:33789,56773:33750,56774:33820,56775:33848,56776:33809,56777:33798,56778:33748,56779:33759,56780:33807,56781:33795,56782:33784,56783:33785,56784:33770,56785:33733,56786:33728,56787:33830,56788:33776,56789:33761,56790:33884,56791:33873,56792:33882,56793:33881,56794:33907,56795:33927,56796:33928,56797:33914,56798:33929,56799:33912,56800:33852,56801:33862,56802:33897,56803:33910,56804:33932,56805:33934,56806:33841,56807:33901,56808:33985,56809:33997,56810:34000,56811:34022,56812:33981,56813:34003,56814:33994,56815:33983,56816:33978,56817:34016,56818:33953,56819:33977,56820:33972,56821:33943,56822:34021,56823:34019,56824:34060,56825:29965,56826:34104,56827:34032,56828:34105,56829:34079,56830:34106,56896:36677,56897:36678,56898:36679,56899:36680,56900:36681,56901:36682,56902:36683,56903:36684,56904:36685,56905:36686,56906:36687,56907:36688,56908:36689,56909:36690,56910:36691,56911:36692,56912:36693,56913:36694,56914:36695,56915:36696,56916:36697,56917:36698,56918:36699,56919:36700,56920:36701,56921:36702,56922:36703,56923:36704,56924:36705,56925:36706,56926:36707,56927:36708,56928:36709,56929:36714,56930:36736,56931:36748,56932:36754,56933:36765,56934:36768,56935:36769,56936:36770,56937:36772,56938:36773,56939:36774,56940:36775,56941:36778,56942:36780,56943:36781,56944:36782,56945:36783,56946:36786,56947:36787,56948:36788,56949:36789,56950:36791,56951:36792,56952:36794,56953:36795,56954:36796,56955:36799,56956:36800,56957:36803,56958:36806,56960:36809,56961:36810,56962:36811,56963:36812,56964:36813,56965:36815,56966:36818,56967:36822,56968:36823,56969:36826,56970:36832,56971:36833,56972:36835,56973:36839,56974:36844,56975:36847,56976:36849,56977:36850,56978:36852,56979:36853,56980:36854,56981:36858,56982:36859,56983:36860,56984:36862,56985:36863,56986:36871,56987:36872,56988:36876,56989:36878,56990:36883,56991:36885,56992:36888,56993:34134,56994:34107,56995:34047,56996:34044,56997:34137,56998:34120,56999:34152,57000:34148,57001:34142,57002:34170,57003:30626,57004:34115,57005:34162,57006:34171,57007:34212,57008:34216,57009:34183,57010:34191,57011:34169,57012:34222,57013:34204,57014:34181,57015:34233,57016:34231,57017:34224,57018:34259,57019:34241,57020:34268,57021:34303,57022:34343,57023:34309,57024:34345,57025:34326,57026:34364,57027:24318,57028:24328,57029:22844,57030:22849,57031:32823,57032:22869,57033:22874,57034:22872,57035:21263,57036:23586,57037:23589,57038:23596,57039:23604,57040:25164,57041:25194,57042:25247,57043:25275,57044:25290,57045:25306,57046:25303,57047:25326,57048:25378,57049:25334,57050:25401,57051:25419,57052:25411,57053:25517,57054:25590,57055:25457,57056:25466,57057:25486,57058:25524,57059:25453,57060:25516,57061:25482,57062:25449,57063:25518,57064:25532,57065:25586,57066:25592,57067:25568,57068:25599,57069:25540,57070:25566,57071:25550,57072:25682,57073:25542,57074:25534,57075:25669,57076:25665,57077:25611,57078:25627,57079:25632,57080:25612,57081:25638,57082:25633,57083:25694,57084:25732,57085:25709,57086:25750,57152:36889,57153:36892,57154:36899,57155:36900,57156:36901,57157:36903,57158:36904,57159:36905,57160:36906,57161:36907,57162:36908,57163:36912,57164:36913,57165:36914,57166:36915,57167:36916,57168:36919,57169:36921,57170:36922,57171:36925,57172:36927,57173:36928,57174:36931,57175:36933,57176:36934,57177:36936,57178:36937,57179:36938,57180:36939,57181:36940,57182:36942,57183:36948,57184:36949,57185:36950,57186:36953,57187:36954,57188:36956,57189:36957,57190:36958,57191:36959,57192:36960,57193:36961,57194:36964,57195:36966,57196:36967,57197:36969,57198:36970,57199:36971,57200:36972,57201:36975,57202:36976,57203:36977,57204:36978,57205:36979,57206:36982,57207:36983,57208:36984,57209:36985,57210:36986,57211:36987,57212:36988,57213:36990,57214:36993,57216:36996,57217:36997,57218:36998,57219:36999,57220:37001,57221:37002,57222:37004,57223:37005,57224:37006,57225:37007,57226:37008,57227:37010,57228:37012,57229:37014,57230:37016,57231:37018,57232:37020,57233:37022,57234:37023,57235:37024,57236:37028,57237:37029,57238:37031,57239:37032,57240:37033,57241:37035,57242:37037,57243:37042,57244:37047,57245:37052,57246:37053,57247:37055,57248:37056,57249:25722,57250:25783,57251:25784,57252:25753,57253:25786,57254:25792,57255:25808,57256:25815,57257:25828,57258:25826,57259:25865,57260:25893,57261:25902,57262:24331,57263:24530,57264:29977,57265:24337,57266:21343,57267:21489,57268:21501,57269:21481,57270:21480,57271:21499,57272:21522,57273:21526,57274:21510,57275:21579,57276:21586,57277:21587,57278:21588,57279:21590,57280:21571,57281:21537,57282:21591,57283:21593,57284:21539,57285:21554,57286:21634,57287:21652,57288:21623,57289:21617,57290:21604,57291:21658,57292:21659,57293:21636,57294:21622,57295:21606,57296:21661,57297:21712,57298:21677,57299:21698,57300:21684,57301:21714,57302:21671,57303:21670,57304:21715,57305:21716,57306:21618,57307:21667,57308:21717,57309:21691,57310:21695,57311:21708,57312:21721,57313:21722,57314:21724,57315:21673,57316:21674,57317:21668,57318:21725,57319:21711,57320:21726,57321:21787,57322:21735,57323:21792,57324:21757,57325:21780,57326:21747,57327:21794,57328:21795,57329:21775,57330:21777,57331:21799,57332:21802,57333:21863,57334:21903,57335:21941,57336:21833,57337:21869,57338:21825,57339:21845,57340:21823,57341:21840,57342:21820,57408:37058,57409:37059,57410:37062,57411:37064,57412:37065,57413:37067,57414:37068,57415:37069,57416:37074,57417:37076,57418:37077,57419:37078,57420:37080,57421:37081,57422:37082,57423:37086,57424:37087,57425:37088,57426:37091,57427:37092,57428:37093,57429:37097,57430:37098,57431:37100,57432:37102,57433:37104,57434:37105,57435:37106,57436:37107,57437:37109,57438:37110,57439:37111,57440:37113,57441:37114,57442:37115,57443:37116,57444:37119,57445:37120,57446:37121,57447:37123,57448:37125,57449:37126,57450:37127,57451:37128,57452:37129,57453:37130,57454:37131,57455:37132,57456:37133,57457:37134,57458:37135,57459:37136,57460:37137,57461:37138,57462:37139,57463:37140,57464:37141,57465:37142,57466:37143,57467:37144,57468:37146,57469:37147,57470:37148,57472:37149,57473:37151,57474:37152,57475:37153,57476:37156,57477:37157,57478:37158,57479:37159,57480:37160,57481:37161,57482:37162,57483:37163,57484:37164,57485:37165,57486:37166,57487:37168,57488:37170,57489:37171,57490:37172,57491:37173,57492:37174,57493:37175,57494:37176,57495:37178,57496:37179,57497:37180,57498:37181,57499:37182,57500:37183,57501:37184,57502:37185,57503:37186,57504:37188,57505:21815,57506:21846,57507:21877,57508:21878,57509:21879,57510:21811,57511:21808,57512:21852,57513:21899,57514:21970,57515:21891,57516:21937,57517:21945,57518:21896,57519:21889,57520:21919,57521:21886,57522:21974,57523:21905,57524:21883,57525:21983,57526:21949,57527:21950,57528:21908,57529:21913,57530:21994,57531:22007,57532:21961,57533:22047,57534:21969,57535:21995,57536:21996,57537:21972,57538:21990,57539:21981,57540:21956,57541:21999,57542:21989,57543:22002,57544:22003,57545:21964,57546:21965,57547:21992,57548:22005,57549:21988,57550:36756,57551:22046,57552:22024,57553:22028,57554:22017,57555:22052,57556:22051,57557:22014,57558:22016,57559:22055,57560:22061,57561:22104,57562:22073,57563:22103,57564:22060,57565:22093,57566:22114,57567:22105,57568:22108,57569:22092,57570:22100,57571:22150,57572:22116,57573:22129,57574:22123,57575:22139,57576:22140,57577:22149,57578:22163,57579:22191,57580:22228,57581:22231,57582:22237,57583:22241,57584:22261,57585:22251,57586:22265,57587:22271,57588:22276,57589:22282,57590:22281,57591:22300,57592:24079,57593:24089,57594:24084,57595:24081,57596:24113,57597:24123,57598:24124,57664:37189,57665:37191,57666:37192,57667:37201,57668:37203,57669:37204,57670:37205,57671:37206,57672:37208,57673:37209,57674:37211,57675:37212,57676:37215,57677:37216,57678:37222,57679:37223,57680:37224,57681:37227,57682:37229,57683:37235,57684:37242,57685:37243,57686:37244,57687:37248,57688:37249,57689:37250,57690:37251,57691:37252,57692:37254,57693:37256,57694:37258,57695:37262,57696:37263,57697:37267,57698:37268,57699:37269,57700:37270,57701:37271,57702:37272,57703:37273,57704:37276,57705:37277,57706:37278,57707:37279,57708:37280,57709:37281,57710:37284,57711:37285,57712:37286,57713:37287,57714:37288,57715:37289,57716:37291,57717:37292,57718:37296,57719:37297,57720:37298,57721:37299,57722:37302,57723:37303,57724:37304,57725:37305,57726:37307,57728:37308,57729:37309,57730:37310,57731:37311,57732:37312,57733:37313,57734:37314,57735:37315,57736:37316,57737:37317,57738:37318,57739:37320,57740:37323,57741:37328,57742:37330,57743:37331,57744:37332,57745:37333,57746:37334,57747:37335,57748:37336,57749:37337,57750:37338,57751:37339,57752:37341,57753:37342,57754:37343,57755:37344,57756:37345,57757:37346,57758:37347,57759:37348,57760:37349,57761:24119,57762:24132,57763:24148,57764:24155,57765:24158,57766:24161,57767:23692,57768:23674,57769:23693,57770:23696,57771:23702,57772:23688,57773:23704,57774:23705,57775:23697,57776:23706,57777:23708,57778:23733,57779:23714,57780:23741,57781:23724,57782:23723,57783:23729,57784:23715,57785:23745,57786:23735,57787:23748,57788:23762,57789:23780,57790:23755,57791:23781,57792:23810,57793:23811,57794:23847,57795:23846,57796:23854,57797:23844,57798:23838,57799:23814,57800:23835,57801:23896,57802:23870,57803:23860,57804:23869,57805:23916,57806:23899,57807:23919,57808:23901,57809:23915,57810:23883,57811:23882,57812:23913,57813:23924,57814:23938,57815:23961,57816:23965,57817:35955,57818:23991,57819:24005,57820:24435,57821:24439,57822:24450,57823:24455,57824:24457,57825:24460,57826:24469,57827:24473,57828:24476,57829:24488,57830:24493,57831:24501,57832:24508,57833:34914,57834:24417,57835:29357,57836:29360,57837:29364,57838:29367,57839:29368,57840:29379,57841:29377,57842:29390,57843:29389,57844:29394,57845:29416,57846:29423,57847:29417,57848:29426,57849:29428,57850:29431,57851:29441,57852:29427,57853:29443,57854:29434,57920:37350,57921:37351,57922:37352,57923:37353,57924:37354,57925:37355,57926:37356,57927:37357,57928:37358,57929:37359,57930:37360,57931:37361,57932:37362,57933:37363,57934:37364,57935:37365,57936:37366,57937:37367,57938:37368,57939:37369,57940:37370,57941:37371,57942:37372,57943:37373,57944:37374,57945:37375,57946:37376,57947:37377,57948:37378,57949:37379,57950:37380,57951:37381,57952:37382,57953:37383,57954:37384,57955:37385,57956:37386,57957:37387,57958:37388,57959:37389,57960:37390,57961:37391,57962:37392,57963:37393,57964:37394,57965:37395,57966:37396,57967:37397,57968:37398,57969:37399,57970:37400,57971:37401,57972:37402,57973:37403,57974:37404,57975:37405,57976:37406,57977:37407,57978:37408,57979:37409,57980:37410,57981:37411,57982:37412,57984:37413,57985:37414,57986:37415,57987:37416,57988:37417,57989:37418,57990:37419,57991:37420,57992:37421,57993:37422,57994:37423,57995:37424,57996:37425,57997:37426,57998:37427,57999:37428,58000:37429,58001:37430,58002:37431,58003:37432,58004:37433,58005:37434,58006:37435,58007:37436,58008:37437,58009:37438,58010:37439,58011:37440,58012:37441,58013:37442,58014:37443,58015:37444,58016:37445,58017:29435,58018:29463,58019:29459,58020:29473,58021:29450,58022:29470,58023:29469,58024:29461,58025:29474,58026:29497,58027:29477,58028:29484,58029:29496,58030:29489,58031:29520,58032:29517,58033:29527,58034:29536,58035:29548,58036:29551,58037:29566,58038:33307,58039:22821,58040:39143,58041:22820,58042:22786,58043:39267,58044:39271,58045:39272,58046:39273,58047:39274,58048:39275,58049:39276,58050:39284,58051:39287,58052:39293,58053:39296,58054:39300,58055:39303,58056:39306,58057:39309,58058:39312,58059:39313,58060:39315,58061:39316,58062:39317,58063:24192,58064:24209,58065:24203,58066:24214,58067:24229,58068:24224,58069:24249,58070:24245,58071:24254,58072:24243,58073:36179,58074:24274,58075:24273,58076:24283,58077:24296,58078:24298,58079:33210,58080:24516,58081:24521,58082:24534,58083:24527,58084:24579,58085:24558,58086:24580,58087:24545,58088:24548,58089:24574,58090:24581,58091:24582,58092:24554,58093:24557,58094:24568,58095:24601,58096:24629,58097:24614,58098:24603,58099:24591,58100:24589,58101:24617,58102:24619,58103:24586,58104:24639,58105:24609,58106:24696,58107:24697,58108:24699,58109:24698,58110:24642,58176:37446,58177:37447,58178:37448,58179:37449,58180:37450,58181:37451,58182:37452,58183:37453,58184:37454,58185:37455,58186:37456,58187:37457,58188:37458,58189:37459,58190:37460,58191:37461,58192:37462,58193:37463,58194:37464,58195:37465,58196:37466,58197:37467,58198:37468,58199:37469,58200:37470,58201:37471,58202:37472,58203:37473,58204:37474,58205:37475,58206:37476,58207:37477,58208:37478,58209:37479,58210:37480,58211:37481,58212:37482,58213:37483,58214:37484,58215:37485,58216:37486,58217:37487,58218:37488,58219:37489,58220:37490,58221:37491,58222:37493,58223:37494,58224:37495,58225:37496,58226:37497,58227:37498,58228:37499,58229:37500,58230:37501,58231:37502,58232:37503,58233:37504,58234:37505,58235:37506,58236:37507,58237:37508,58238:37509,58240:37510,58241:37511,58242:37512,58243:37513,58244:37514,58245:37515,58246:37516,58247:37517,58248:37519,58249:37520,58250:37521,58251:37522,58252:37523,58253:37524,58254:37525,58255:37526,58256:37527,58257:37528,58258:37529,58259:37530,58260:37531,58261:37532,58262:37533,58263:37534,58264:37535,58265:37536,58266:37537,58267:37538,58268:37539,58269:37540,58270:37541,58271:37542,58272:37543,58273:24682,58274:24701,58275:24726,58276:24730,58277:24749,58278:24733,58279:24707,58280:24722,58281:24716,58282:24731,58283:24812,58284:24763,58285:24753,58286:24797,58287:24792,58288:24774,58289:24794,58290:24756,58291:24864,58292:24870,58293:24853,58294:24867,58295:24820,58296:24832,58297:24846,58298:24875,58299:24906,58300:24949,58301:25004,58302:24980,58303:24999,58304:25015,58305:25044,58306:25077,58307:24541,58308:38579,58309:38377,58310:38379,58311:38385,58312:38387,58313:38389,58314:38390,58315:38396,58316:38398,58317:38403,58318:38404,58319:38406,58320:38408,58321:38410,58322:38411,58323:38412,58324:38413,58325:38415,58326:38418,58327:38421,58328:38422,58329:38423,58330:38425,58331:38426,58332:20012,58333:29247,58334:25109,58335:27701,58336:27732,58337:27740,58338:27722,58339:27811,58340:27781,58341:27792,58342:27796,58343:27788,58344:27752,58345:27753,58346:27764,58347:27766,58348:27782,58349:27817,58350:27856,58351:27860,58352:27821,58353:27895,58354:27896,58355:27889,58356:27863,58357:27826,58358:27872,58359:27862,58360:27898,58361:27883,58362:27886,58363:27825,58364:27859,58365:27887,58366:27902,58432:37544,58433:37545,58434:37546,58435:37547,58436:37548,58437:37549,58438:37551,58439:37552,58440:37553,58441:37554,58442:37555,58443:37556,58444:37557,58445:37558,58446:37559,58447:37560,58448:37561,58449:37562,58450:37563,58451:37564,58452:37565,58453:37566,58454:37567,58455:37568,58456:37569,58457:37570,58458:37571,58459:37572,58460:37573,58461:37574,58462:37575,58463:37577,58464:37578,58465:37579,58466:37580,58467:37581,58468:37582,58469:37583,58470:37584,58471:37585,58472:37586,58473:37587,58474:37588,58475:37589,58476:37590,58477:37591,58478:37592,58479:37593,58480:37594,58481:37595,58482:37596,58483:37597,58484:37598,58485:37599,58486:37600,58487:37601,58488:37602,58489:37603,58490:37604,58491:37605,58492:37606,58493:37607,58494:37608,58496:37609,58497:37610,58498:37611,58499:37612,58500:37613,58501:37614,58502:37615,58503:37616,58504:37617,58505:37618,58506:37619,58507:37620,58508:37621,58509:37622,58510:37623,58511:37624,58512:37625,58513:37626,58514:37627,58515:37628,58516:37629,58517:37630,58518:37631,58519:37632,58520:37633,58521:37634,58522:37635,58523:37636,58524:37637,58525:37638,58526:37639,58527:37640,58528:37641,58529:27961,58530:27943,58531:27916,58532:27971,58533:27976,58534:27911,58535:27908,58536:27929,58537:27918,58538:27947,58539:27981,58540:27950,58541:27957,58542:27930,58543:27983,58544:27986,58545:27988,58546:27955,58547:28049,58548:28015,58549:28062,58550:28064,58551:27998,58552:28051,58553:28052,58554:27996,58555:28000,58556:28028,58557:28003,58558:28186,58559:28103,58560:28101,58561:28126,58562:28174,58563:28095,58564:28128,58565:28177,58566:28134,58567:28125,58568:28121,58569:28182,58570:28075,58571:28172,58572:28078,58573:28203,58574:28270,58575:28238,58576:28267,58577:28338,58578:28255,58579:28294,58580:28243,58581:28244,58582:28210,58583:28197,58584:28228,58585:28383,58586:28337,58587:28312,58588:28384,58589:28461,58590:28386,58591:28325,58592:28327,58593:28349,58594:28347,58595:28343,58596:28375,58597:28340,58598:28367,58599:28303,58600:28354,58601:28319,58602:28514,58603:28486,58604:28487,58605:28452,58606:28437,58607:28409,58608:28463,58609:28470,58610:28491,58611:28532,58612:28458,58613:28425,58614:28457,58615:28553,58616:28557,58617:28556,58618:28536,58619:28530,58620:28540,58621:28538,58622:28625,58688:37642,58689:37643,58690:37644,58691:37645,58692:37646,58693:37647,58694:37648,58695:37649,58696:37650,58697:37651,58698:37652,58699:37653,58700:37654,58701:37655,58702:37656,58703:37657,58704:37658,58705:37659,58706:37660,58707:37661,58708:37662,58709:37663,58710:37664,58711:37665,58712:37666,58713:37667,58714:37668,58715:37669,58716:37670,58717:37671,58718:37672,58719:37673,58720:37674,58721:37675,58722:37676,58723:37677,58724:37678,58725:37679,58726:37680,58727:37681,58728:37682,58729:37683,58730:37684,58731:37685,58732:37686,58733:37687,58734:37688,58735:37689,58736:37690,58737:37691,58738:37692,58739:37693,58740:37695,58741:37696,58742:37697,58743:37698,58744:37699,58745:37700,58746:37701,58747:37702,58748:37703,58749:37704,58750:37705,58752:37706,58753:37707,58754:37708,58755:37709,58756:37710,58757:37711,58758:37712,58759:37713,58760:37714,58761:37715,58762:37716,58763:37717,58764:37718,58765:37719,58766:37720,58767:37721,58768:37722,58769:37723,58770:37724,58771:37725,58772:37726,58773:37727,58774:37728,58775:37729,58776:37730,58777:37731,58778:37732,58779:37733,58780:37734,58781:37735,58782:37736,58783:37737,58784:37739,58785:28617,58786:28583,58787:28601,58788:28598,58789:28610,58790:28641,58791:28654,58792:28638,58793:28640,58794:28655,58795:28698,58796:28707,58797:28699,58798:28729,58799:28725,58800:28751,58801:28766,58802:23424,58803:23428,58804:23445,58805:23443,58806:23461,58807:23480,58808:29999,58809:39582,58810:25652,58811:23524,58812:23534,58813:35120,58814:23536,58815:36423,58816:35591,58817:36790,58818:36819,58819:36821,58820:36837,58821:36846,58822:36836,58823:36841,58824:36838,58825:36851,58826:36840,58827:36869,58828:36868,58829:36875,58830:36902,58831:36881,58832:36877,58833:36886,58834:36897,58835:36917,58836:36918,58837:36909,58838:36911,58839:36932,58840:36945,58841:36946,58842:36944,58843:36968,58844:36952,58845:36962,58846:36955,58847:26297,58848:36980,58849:36989,58850:36994,58851:37000,58852:36995,58853:37003,58854:24400,58855:24407,58856:24406,58857:24408,58858:23611,58859:21675,58860:23632,58861:23641,58862:23409,58863:23651,58864:23654,58865:32700,58866:24362,58867:24361,58868:24365,58869:33396,58870:24380,58871:39739,58872:23662,58873:22913,58874:22915,58875:22925,58876:22953,58877:22954,58878:22947,58944:37740,58945:37741,58946:37742,58947:37743,58948:37744,58949:37745,58950:37746,58951:37747,58952:37748,58953:37749,58954:37750,58955:37751,58956:37752,58957:37753,58958:37754,58959:37755,58960:37756,58961:37757,58962:37758,58963:37759,58964:37760,58965:37761,58966:37762,58967:37763,58968:37764,58969:37765,58970:37766,58971:37767,58972:37768,58973:37769,58974:37770,58975:37771,58976:37772,58977:37773,58978:37774,58979:37776,58980:37777,58981:37778,58982:37779,58983:37780,58984:37781,58985:37782,58986:37783,58987:37784,58988:37785,58989:37786,58990:37787,58991:37788,58992:37789,58993:37790,58994:37791,58995:37792,58996:37793,58997:37794,58998:37795,58999:37796,59000:37797,59001:37798,59002:37799,59003:37800,59004:37801,59005:37802,59006:37803,59008:37804,59009:37805,59010:37806,59011:37807,59012:37808,59013:37809,59014:37810,59015:37811,59016:37812,59017:37813,59018:37814,59019:37815,59020:37816,59021:37817,59022:37818,59023:37819,59024:37820,59025:37821,59026:37822,59027:37823,59028:37824,59029:37825,59030:37826,59031:37827,59032:37828,59033:37829,59034:37830,59035:37831,59036:37832,59037:37833,59038:37835,59039:37836,59040:37837,59041:22935,59042:22986,59043:22955,59044:22942,59045:22948,59046:22994,59047:22962,59048:22959,59049:22999,59050:22974,59051:23045,59052:23046,59053:23005,59054:23048,59055:23011,59056:23000,59057:23033,59058:23052,59059:23049,59060:23090,59061:23092,59062:23057,59063:23075,59064:23059,59065:23104,59066:23143,59067:23114,59068:23125,59069:23100,59070:23138,59071:23157,59072:33004,59073:23210,59074:23195,59075:23159,59076:23162,59077:23230,59078:23275,59079:23218,59080:23250,59081:23252,59082:23224,59083:23264,59084:23267,59085:23281,59086:23254,59087:23270,59088:23256,59089:23260,59090:23305,59091:23319,59092:23318,59093:23346,59094:23351,59095:23360,59096:23573,59097:23580,59098:23386,59099:23397,59100:23411,59101:23377,59102:23379,59103:23394,59104:39541,59105:39543,59106:39544,59107:39546,59108:39551,59109:39549,59110:39552,59111:39553,59112:39557,59113:39560,59114:39562,59115:39568,59116:39570,59117:39571,59118:39574,59119:39576,59120:39579,59121:39580,59122:39581,59123:39583,59124:39584,59125:39586,59126:39587,59127:39589,59128:39591,59129:32415,59130:32417,59131:32419,59132:32421,59133:32424,59134:32425,59200:37838,59201:37839,59202:37840,59203:37841,59204:37842,59205:37843,59206:37844,59207:37845,59208:37847,59209:37848,59210:37849,59211:37850,59212:37851,59213:37852,59214:37853,59215:37854,59216:37855,59217:37856,59218:37857,59219:37858,59220:37859,59221:37860,59222:37861,59223:37862,59224:37863,59225:37864,59226:37865,59227:37866,59228:37867,59229:37868,59230:37869,59231:37870,59232:37871,59233:37872,59234:37873,59235:37874,59236:37875,59237:37876,59238:37877,59239:37878,59240:37879,59241:37880,59242:37881,59243:37882,59244:37883,59245:37884,59246:37885,59247:37886,59248:37887,59249:37888,59250:37889,59251:37890,59252:37891,59253:37892,59254:37893,59255:37894,59256:37895,59257:37896,59258:37897,59259:37898,59260:37899,59261:37900,59262:37901,59264:37902,59265:37903,59266:37904,59267:37905,59268:37906,59269:37907,59270:37908,59271:37909,59272:37910,59273:37911,59274:37912,59275:37913,59276:37914,59277:37915,59278:37916,59279:37917,59280:37918,59281:37919,59282:37920,59283:37921,59284:37922,59285:37923,59286:37924,59287:37925,59288:37926,59289:37927,59290:37928,59291:37929,59292:37930,59293:37931,59294:37932,59295:37933,59296:37934,59297:32429,59298:32432,59299:32446,59300:32448,59301:32449,59302:32450,59303:32457,59304:32459,59305:32460,59306:32464,59307:32468,59308:32471,59309:32475,59310:32480,59311:32481,59312:32488,59313:32491,59314:32494,59315:32495,59316:32497,59317:32498,59318:32525,59319:32502,59320:32506,59321:32507,59322:32510,59323:32513,59324:32514,59325:32515,59326:32519,59327:32520,59328:32523,59329:32524,59330:32527,59331:32529,59332:32530,59333:32535,59334:32537,59335:32540,59336:32539,59337:32543,59338:32545,59339:32546,59340:32547,59341:32548,59342:32549,59343:32550,59344:32551,59345:32554,59346:32555,59347:32556,59348:32557,59349:32559,59350:32560,59351:32561,59352:32562,59353:32563,59354:32565,59355:24186,59356:30079,59357:24027,59358:30014,59359:37013,59360:29582,59361:29585,59362:29614,59363:29602,59364:29599,59365:29647,59366:29634,59367:29649,59368:29623,59369:29619,59370:29632,59371:29641,59372:29640,59373:29669,59374:29657,59375:39036,59376:29706,59377:29673,59378:29671,59379:29662,59380:29626,59381:29682,59382:29711,59383:29738,59384:29787,59385:29734,59386:29733,59387:29736,59388:29744,59389:29742,59390:29740,59456:37935,59457:37936,59458:37937,59459:37938,59460:37939,59461:37940,59462:37941,59463:37942,59464:37943,59465:37944,59466:37945,59467:37946,59468:37947,59469:37948,59470:37949,59471:37951,59472:37952,59473:37953,59474:37954,59475:37955,59476:37956,59477:37957,59478:37958,59479:37959,59480:37960,59481:37961,59482:37962,59483:37963,59484:37964,59485:37965,59486:37966,59487:37967,59488:37968,59489:37969,59490:37970,59491:37971,59492:37972,59493:37973,59494:37974,59495:37975,59496:37976,59497:37977,59498:37978,59499:37979,59500:37980,59501:37981,59502:37982,59503:37983,59504:37984,59505:37985,59506:37986,59507:37987,59508:37988,59509:37989,59510:37990,59511:37991,59512:37992,59513:37993,59514:37994,59515:37996,59516:37997,59517:37998,59518:37999,59520:38000,59521:38001,59522:38002,59523:38003,59524:38004,59525:38005,59526:38006,59527:38007,59528:38008,59529:38009,59530:38010,59531:38011,59532:38012,59533:38013,59534:38014,59535:38015,59536:38016,59537:38017,59538:38018,59539:38019,59540:38020,59541:38033,59542:38038,59543:38040,59544:38087,59545:38095,59546:38099,59547:38100,59548:38106,59549:38118,59550:38139,59551:38172,59552:38176,59553:29723,59554:29722,59555:29761,59556:29788,59557:29783,59558:29781,59559:29785,59560:29815,59561:29805,59562:29822,59563:29852,59564:29838,59565:29824,59566:29825,59567:29831,59568:29835,59569:29854,59570:29864,59571:29865,59572:29840,59573:29863,59574:29906,59575:29882,59576:38890,59577:38891,59578:38892,59579:26444,59580:26451,59581:26462,59582:26440,59583:26473,59584:26533,59585:26503,59586:26474,59587:26483,59588:26520,59589:26535,59590:26485,59591:26536,59592:26526,59593:26541,59594:26507,59595:26487,59596:26492,59597:26608,59598:26633,59599:26584,59600:26634,59601:26601,59602:26544,59603:26636,59604:26585,59605:26549,59606:26586,59607:26547,59608:26589,59609:26624,59610:26563,59611:26552,59612:26594,59613:26638,59614:26561,59615:26621,59616:26674,59617:26675,59618:26720,59619:26721,59620:26702,59621:26722,59622:26692,59623:26724,59624:26755,59625:26653,59626:26709,59627:26726,59628:26689,59629:26727,59630:26688,59631:26686,59632:26698,59633:26697,59634:26665,59635:26805,59636:26767,59637:26740,59638:26743,59639:26771,59640:26731,59641:26818,59642:26990,59643:26876,59644:26911,59645:26912,59646:26873,59712:38183,59713:38195,59714:38205,59715:38211,59716:38216,59717:38219,59718:38229,59719:38234,59720:38240,59721:38254,59722:38260,59723:38261,59724:38263,59725:38264,59726:38265,59727:38266,59728:38267,59729:38268,59730:38269,59731:38270,59732:38272,59733:38273,59734:38274,59735:38275,59736:38276,59737:38277,59738:38278,59739:38279,59740:38280,59741:38281,59742:38282,59743:38283,59744:38284,59745:38285,59746:38286,59747:38287,59748:38288,59749:38289,59750:38290,59751:38291,59752:38292,59753:38293,59754:38294,59755:38295,59756:38296,59757:38297,59758:38298,59759:38299,59760:38300,59761:38301,59762:38302,59763:38303,59764:38304,59765:38305,59766:38306,59767:38307,59768:38308,59769:38309,59770:38310,59771:38311,59772:38312,59773:38313,59774:38314,59776:38315,59777:38316,59778:38317,59779:38318,59780:38319,59781:38320,59782:38321,59783:38322,59784:38323,59785:38324,59786:38325,59787:38326,59788:38327,59789:38328,59790:38329,59791:38330,59792:38331,59793:38332,59794:38333,59795:38334,59796:38335,59797:38336,59798:38337,59799:38338,59800:38339,59801:38340,59802:38341,59803:38342,59804:38343,59805:38344,59806:38345,59807:38346,59808:38347,59809:26916,59810:26864,59811:26891,59812:26881,59813:26967,59814:26851,59815:26896,59816:26993,59817:26937,59818:26976,59819:26946,59820:26973,59821:27012,59822:26987,59823:27008,59824:27032,59825:27000,59826:26932,59827:27084,59828:27015,59829:27016,59830:27086,59831:27017,59832:26982,59833:26979,59834:27001,59835:27035,59836:27047,59837:27067,59838:27051,59839:27053,59840:27092,59841:27057,59842:27073,59843:27082,59844:27103,59845:27029,59846:27104,59847:27021,59848:27135,59849:27183,59850:27117,59851:27159,59852:27160,59853:27237,59854:27122,59855:27204,59856:27198,59857:27296,59858:27216,59859:27227,59860:27189,59861:27278,59862:27257,59863:27197,59864:27176,59865:27224,59866:27260,59867:27281,59868:27280,59869:27305,59870:27287,59871:27307,59872:29495,59873:29522,59874:27521,59875:27522,59876:27527,59877:27524,59878:27538,59879:27539,59880:27533,59881:27546,59882:27547,59883:27553,59884:27562,59885:36715,59886:36717,59887:36721,59888:36722,59889:36723,59890:36725,59891:36726,59892:36728,59893:36727,59894:36729,59895:36730,59896:36732,59897:36734,59898:36737,59899:36738,59900:36740,59901:36743,59902:36747,59968:38348,59969:38349,59970:38350,59971:38351,59972:38352,59973:38353,59974:38354,59975:38355,59976:38356,59977:38357,59978:38358,59979:38359,59980:38360,59981:38361,59982:38362,59983:38363,59984:38364,59985:38365,59986:38366,59987:38367,59988:38368,59989:38369,59990:38370,59991:38371,59992:38372,59993:38373,59994:38374,59995:38375,59996:38380,59997:38399,59998:38407,59999:38419,60000:38424,60001:38427,60002:38430,60003:38432,60004:38435,60005:38436,60006:38437,60007:38438,60008:38439,60009:38440,60010:38441,60011:38443,60012:38444,60013:38445,60014:38447,60015:38448,60016:38455,60017:38456,60018:38457,60019:38458,60020:38462,60021:38465,60022:38467,60023:38474,60024:38478,60025:38479,60026:38481,60027:38482,60028:38483,60029:38486,60030:38487,60032:38488,60033:38489,60034:38490,60035:38492,60036:38493,60037:38494,60038:38496,60039:38499,60040:38501,60041:38502,60042:38507,60043:38509,60044:38510,60045:38511,60046:38512,60047:38513,60048:38515,60049:38520,60050:38521,60051:38522,60052:38523,60053:38524,60054:38525,60055:38526,60056:38527,60057:38528,60058:38529,60059:38530,60060:38531,60061:38532,60062:38535,60063:38537,60064:38538,60065:36749,60066:36750,60067:36751,60068:36760,60069:36762,60070:36558,60071:25099,60072:25111,60073:25115,60074:25119,60075:25122,60076:25121,60077:25125,60078:25124,60079:25132,60080:33255,60081:29935,60082:29940,60083:29951,60084:29967,60085:29969,60086:29971,60087:25908,60088:26094,60089:26095,60090:26096,60091:26122,60092:26137,60093:26482,60094:26115,60095:26133,60096:26112,60097:28805,60098:26359,60099:26141,60100:26164,60101:26161,60102:26166,60103:26165,60104:32774,60105:26207,60106:26196,60107:26177,60108:26191,60109:26198,60110:26209,60111:26199,60112:26231,60113:26244,60114:26252,60115:26279,60116:26269,60117:26302,60118:26331,60119:26332,60120:26342,60121:26345,60122:36146,60123:36147,60124:36150,60125:36155,60126:36157,60127:36160,60128:36165,60129:36166,60130:36168,60131:36169,60132:36167,60133:36173,60134:36181,60135:36185,60136:35271,60137:35274,60138:35275,60139:35276,60140:35278,60141:35279,60142:35280,60143:35281,60144:29294,60145:29343,60146:29277,60147:29286,60148:29295,60149:29310,60150:29311,60151:29316,60152:29323,60153:29325,60154:29327,60155:29330,60156:25352,60157:25394,60158:25520,60224:38540,60225:38542,60226:38545,60227:38546,60228:38547,60229:38549,60230:38550,60231:38554,60232:38555,60233:38557,60234:38558,60235:38559,60236:38560,60237:38561,60238:38562,60239:38563,60240:38564,60241:38565,60242:38566,60243:38568,60244:38569,60245:38570,60246:38571,60247:38572,60248:38573,60249:38574,60250:38575,60251:38577,60252:38578,60253:38580,60254:38581,60255:38583,60256:38584,60257:38586,60258:38587,60259:38591,60260:38594,60261:38595,60262:38600,60263:38602,60264:38603,60265:38608,60266:38609,60267:38611,60268:38612,60269:38614,60270:38615,60271:38616,60272:38617,60273:38618,60274:38619,60275:38620,60276:38621,60277:38622,60278:38623,60279:38625,60280:38626,60281:38627,60282:38628,60283:38629,60284:38630,60285:38631,60286:38635,60288:38636,60289:38637,60290:38638,60291:38640,60292:38641,60293:38642,60294:38644,60295:38645,60296:38648,60297:38650,60298:38651,60299:38652,60300:38653,60301:38655,60302:38658,60303:38659,60304:38661,60305:38666,60306:38667,60307:38668,60308:38672,60309:38673,60310:38674,60311:38676,60312:38677,60313:38679,60314:38680,60315:38681,60316:38682,60317:38683,60318:38685,60319:38687,60320:38688,60321:25663,60322:25816,60323:32772,60324:27626,60325:27635,60326:27645,60327:27637,60328:27641,60329:27653,60330:27655,60331:27654,60332:27661,60333:27669,60334:27672,60335:27673,60336:27674,60337:27681,60338:27689,60339:27684,60340:27690,60341:27698,60342:25909,60343:25941,60344:25963,60345:29261,60346:29266,60347:29270,60348:29232,60349:34402,60350:21014,60351:32927,60352:32924,60353:32915,60354:32956,60355:26378,60356:32957,60357:32945,60358:32939,60359:32941,60360:32948,60361:32951,60362:32999,60363:33000,60364:33001,60365:33002,60366:32987,60367:32962,60368:32964,60369:32985,60370:32973,60371:32983,60372:26384,60373:32989,60374:33003,60375:33009,60376:33012,60377:33005,60378:33037,60379:33038,60380:33010,60381:33020,60382:26389,60383:33042,60384:35930,60385:33078,60386:33054,60387:33068,60388:33048,60389:33074,60390:33096,60391:33100,60392:33107,60393:33140,60394:33113,60395:33114,60396:33137,60397:33120,60398:33129,60399:33148,60400:33149,60401:33133,60402:33127,60403:22605,60404:23221,60405:33160,60406:33154,60407:33169,60408:28373,60409:33187,60410:33194,60411:33228,60412:26406,60413:33226,60414:33211,60480:38689,60481:38690,60482:38691,60483:38692,60484:38693,60485:38694,60486:38695,60487:38696,60488:38697,60489:38699,60490:38700,60491:38702,60492:38703,60493:38705,60494:38707,60495:38708,60496:38709,60497:38710,60498:38711,60499:38714,60500:38715,60501:38716,60502:38717,60503:38719,60504:38720,60505:38721,60506:38722,60507:38723,60508:38724,60509:38725,60510:38726,60511:38727,60512:38728,60513:38729,60514:38730,60515:38731,60516:38732,60517:38733,60518:38734,60519:38735,60520:38736,60521:38737,60522:38740,60523:38741,60524:38743,60525:38744,60526:38746,60527:38748,60528:38749,60529:38751,60530:38755,60531:38756,60532:38758,60533:38759,60534:38760,60535:38762,60536:38763,60537:38764,60538:38765,60539:38766,60540:38767,60541:38768,60542:38769,60544:38770,60545:38773,60546:38775,60547:38776,60548:38777,60549:38778,60550:38779,60551:38781,60552:38782,60553:38783,60554:38784,60555:38785,60556:38786,60557:38787,60558:38788,60559:38790,60560:38791,60561:38792,60562:38793,60563:38794,60564:38796,60565:38798,60566:38799,60567:38800,60568:38803,60569:38805,60570:38806,60571:38807,60572:38809,60573:38810,60574:38811,60575:38812,60576:38813,60577:33217,60578:33190,60579:27428,60580:27447,60581:27449,60582:27459,60583:27462,60584:27481,60585:39121,60586:39122,60587:39123,60588:39125,60589:39129,60590:39130,60591:27571,60592:24384,60593:27586,60594:35315,60595:26000,60596:40785,60597:26003,60598:26044,60599:26054,60600:26052,60601:26051,60602:26060,60603:26062,60604:26066,60605:26070,60606:28800,60607:28828,60608:28822,60609:28829,60610:28859,60611:28864,60612:28855,60613:28843,60614:28849,60615:28904,60616:28874,60617:28944,60618:28947,60619:28950,60620:28975,60621:28977,60622:29043,60623:29020,60624:29032,60625:28997,60626:29042,60627:29002,60628:29048,60629:29050,60630:29080,60631:29107,60632:29109,60633:29096,60634:29088,60635:29152,60636:29140,60637:29159,60638:29177,60639:29213,60640:29224,60641:28780,60642:28952,60643:29030,60644:29113,60645:25150,60646:25149,60647:25155,60648:25160,60649:25161,60650:31035,60651:31040,60652:31046,60653:31049,60654:31067,60655:31068,60656:31059,60657:31066,60658:31074,60659:31063,60660:31072,60661:31087,60662:31079,60663:31098,60664:31109,60665:31114,60666:31130,60667:31143,60668:31155,60669:24529,60670:24528,60736:38814,60737:38815,60738:38817,60739:38818,60740:38820,60741:38821,60742:38822,60743:38823,60744:38824,60745:38825,60746:38826,60747:38828,60748:38830,60749:38832,60750:38833,60751:38835,60752:38837,60753:38838,60754:38839,60755:38840,60756:38841,60757:38842,60758:38843,60759:38844,60760:38845,60761:38846,60762:38847,60763:38848,60764:38849,60765:38850,60766:38851,60767:38852,60768:38853,60769:38854,60770:38855,60771:38856,60772:38857,60773:38858,60774:38859,60775:38860,60776:38861,60777:38862,60778:38863,60779:38864,60780:38865,60781:38866,60782:38867,60783:38868,60784:38869,60785:38870,60786:38871,60787:38872,60788:38873,60789:38874,60790:38875,60791:38876,60792:38877,60793:38878,60794:38879,60795:38880,60796:38881,60797:38882,60798:38883,60800:38884,60801:38885,60802:38888,60803:38894,60804:38895,60805:38896,60806:38897,60807:38898,60808:38900,60809:38903,60810:38904,60811:38905,60812:38906,60813:38907,60814:38908,60815:38909,60816:38910,60817:38911,60818:38912,60819:38913,60820:38914,60821:38915,60822:38916,60823:38917,60824:38918,60825:38919,60826:38920,60827:38921,60828:38922,60829:38923,60830:38924,60831:38925,60832:38926,60833:24636,60834:24669,60835:24666,60836:24679,60837:24641,60838:24665,60839:24675,60840:24747,60841:24838,60842:24845,60843:24925,60844:25001,60845:24989,60846:25035,60847:25041,60848:25094,60849:32896,60850:32895,60851:27795,60852:27894,60853:28156,60854:30710,60855:30712,60856:30720,60857:30729,60858:30743,60859:30744,60860:30737,60861:26027,60862:30765,60863:30748,60864:30749,60865:30777,60866:30778,60867:30779,60868:30751,60869:30780,60870:30757,60871:30764,60872:30755,60873:30761,60874:30798,60875:30829,60876:30806,60877:30807,60878:30758,60879:30800,60880:30791,60881:30796,60882:30826,60883:30875,60884:30867,60885:30874,60886:30855,60887:30876,60888:30881,60889:30883,60890:30898,60891:30905,60892:30885,60893:30932,60894:30937,60895:30921,60896:30956,60897:30962,60898:30981,60899:30964,60900:30995,60901:31012,60902:31006,60903:31028,60904:40859,60905:40697,60906:40699,60907:40700,60908:30449,60909:30468,60910:30477,60911:30457,60912:30471,60913:30472,60914:30490,60915:30498,60916:30489,60917:30509,60918:30502,60919:30517,60920:30520,60921:30544,60922:30545,60923:30535,60924:30531,60925:30554,60926:30568,60992:38927,60993:38928,60994:38929,60995:38930,60996:38931,60997:38932,60998:38933,60999:38934,61000:38935,61001:38936,61002:38937,61003:38938,61004:38939,61005:38940,61006:38941,61007:38942,61008:38943,61009:38944,61010:38945,61011:38946,61012:38947,61013:38948,61014:38949,61015:38950,61016:38951,61017:38952,61018:38953,61019:38954,61020:38955,61021:38956,61022:38957,61023:38958,61024:38959,61025:38960,61026:38961,61027:38962,61028:38963,61029:38964,61030:38965,61031:38966,61032:38967,61033:38968,61034:38969,61035:38970,61036:38971,61037:38972,61038:38973,61039:38974,61040:38975,61041:38976,61042:38977,61043:38978,61044:38979,61045:38980,61046:38981,61047:38982,61048:38983,61049:38984,61050:38985,61051:38986,61052:38987,61053:38988,61054:38989,61056:38990,61057:38991,61058:38992,61059:38993,61060:38994,61061:38995,61062:38996,61063:38997,61064:38998,61065:38999,61066:39000,61067:39001,61068:39002,61069:39003,61070:39004,61071:39005,61072:39006,61073:39007,61074:39008,61075:39009,61076:39010,61077:39011,61078:39012,61079:39013,61080:39014,61081:39015,61082:39016,61083:39017,61084:39018,61085:39019,61086:39020,61087:39021,61088:39022,61089:30562,61090:30565,61091:30591,61092:30605,61093:30589,61094:30592,61095:30604,61096:30609,61097:30623,61098:30624,61099:30640,61100:30645,61101:30653,61102:30010,61103:30016,61104:30030,61105:30027,61106:30024,61107:30043,61108:30066,61109:30073,61110:30083,61111:32600,61112:32609,61113:32607,61114:35400,61115:32616,61116:32628,61117:32625,61118:32633,61119:32641,61120:32638,61121:30413,61122:30437,61123:34866,61124:38021,61125:38022,61126:38023,61127:38027,61128:38026,61129:38028,61130:38029,61131:38031,61132:38032,61133:38036,61134:38039,61135:38037,61136:38042,61137:38043,61138:38044,61139:38051,61140:38052,61141:38059,61142:38058,61143:38061,61144:38060,61145:38063,61146:38064,61147:38066,61148:38068,61149:38070,61150:38071,61151:38072,61152:38073,61153:38074,61154:38076,61155:38077,61156:38079,61157:38084,61158:38088,61159:38089,61160:38090,61161:38091,61162:38092,61163:38093,61164:38094,61165:38096,61166:38097,61167:38098,61168:38101,61169:38102,61170:38103,61171:38105,61172:38104,61173:38107,61174:38110,61175:38111,61176:38112,61177:38114,61178:38116,61179:38117,61180:38119,61181:38120,61182:38122,61248:39023,61249:39024,61250:39025,61251:39026,61252:39027,61253:39028,61254:39051,61255:39054,61256:39058,61257:39061,61258:39065,61259:39075,61260:39080,61261:39081,61262:39082,61263:39083,61264:39084,61265:39085,61266:39086,61267:39087,61268:39088,61269:39089,61270:39090,61271:39091,61272:39092,61273:39093,61274:39094,61275:39095,61276:39096,61277:39097,61278:39098,61279:39099,61280:39100,61281:39101,61282:39102,61283:39103,61284:39104,61285:39105,61286:39106,61287:39107,61288:39108,61289:39109,61290:39110,61291:39111,61292:39112,61293:39113,61294:39114,61295:39115,61296:39116,61297:39117,61298:39119,61299:39120,61300:39124,61301:39126,61302:39127,61303:39131,61304:39132,61305:39133,61306:39136,61307:39137,61308:39138,61309:39139,61310:39140,61312:39141,61313:39142,61314:39145,61315:39146,61316:39147,61317:39148,61318:39149,61319:39150,61320:39151,61321:39152,61322:39153,61323:39154,61324:39155,61325:39156,61326:39157,61327:39158,61328:39159,61329:39160,61330:39161,61331:39162,61332:39163,61333:39164,61334:39165,61335:39166,61336:39167,61337:39168,61338:39169,61339:39170,61340:39171,61341:39172,61342:39173,61343:39174,61344:39175,61345:38121,61346:38123,61347:38126,61348:38127,61349:38131,61350:38132,61351:38133,61352:38135,61353:38137,61354:38140,61355:38141,61356:38143,61357:38147,61358:38146,61359:38150,61360:38151,61361:38153,61362:38154,61363:38157,61364:38158,61365:38159,61366:38162,61367:38163,61368:38164,61369:38165,61370:38166,61371:38168,61372:38171,61373:38173,61374:38174,61375:38175,61376:38178,61377:38186,61378:38187,61379:38185,61380:38188,61381:38193,61382:38194,61383:38196,61384:38198,61385:38199,61386:38200,61387:38204,61388:38206,61389:38207,61390:38210,61391:38197,61392:38212,61393:38213,61394:38214,61395:38217,61396:38220,61397:38222,61398:38223,61399:38226,61400:38227,61401:38228,61402:38230,61403:38231,61404:38232,61405:38233,61406:38235,61407:38238,61408:38239,61409:38237,61410:38241,61411:38242,61412:38244,61413:38245,61414:38246,61415:38247,61416:38248,61417:38249,61418:38250,61419:38251,61420:38252,61421:38255,61422:38257,61423:38258,61424:38259,61425:38202,61426:30695,61427:30700,61428:38601,61429:31189,61430:31213,61431:31203,61432:31211,61433:31238,61434:23879,61435:31235,61436:31234,61437:31262,61438:31252,61504:39176,61505:39177,61506:39178,61507:39179,61508:39180,61509:39182,61510:39183,61511:39185,61512:39186,61513:39187,61514:39188,61515:39189,61516:39190,61517:39191,61518:39192,61519:39193,61520:39194,61521:39195,61522:39196,61523:39197,61524:39198,61525:39199,61526:39200,61527:39201,61528:39202,61529:39203,61530:39204,61531:39205,61532:39206,61533:39207,61534:39208,61535:39209,61536:39210,61537:39211,61538:39212,61539:39213,61540:39215,61541:39216,61542:39217,61543:39218,61544:39219,61545:39220,61546:39221,61547:39222,61548:39223,61549:39224,61550:39225,61551:39226,61552:39227,61553:39228,61554:39229,61555:39230,61556:39231,61557:39232,61558:39233,61559:39234,61560:39235,61561:39236,61562:39237,61563:39238,61564:39239,61565:39240,61566:39241,61568:39242,61569:39243,61570:39244,61571:39245,61572:39246,61573:39247,61574:39248,61575:39249,61576:39250,61577:39251,61578:39254,61579:39255,61580:39256,61581:39257,61582:39258,61583:39259,61584:39260,61585:39261,61586:39262,61587:39263,61588:39264,61589:39265,61590:39266,61591:39268,61592:39270,61593:39283,61594:39288,61595:39289,61596:39291,61597:39294,61598:39298,61599:39299,61600:39305,61601:31289,61602:31287,61603:31313,61604:40655,61605:39333,61606:31344,61607:30344,61608:30350,61609:30355,61610:30361,61611:30372,61612:29918,61613:29920,61614:29996,61615:40480,61616:40482,61617:40488,61618:40489,61619:40490,61620:40491,61621:40492,61622:40498,61623:40497,61624:40502,61625:40504,61626:40503,61627:40505,61628:40506,61629:40510,61630:40513,61631:40514,61632:40516,61633:40518,61634:40519,61635:40520,61636:40521,61637:40523,61638:40524,61639:40526,61640:40529,61641:40533,61642:40535,61643:40538,61644:40539,61645:40540,61646:40542,61647:40547,61648:40550,61649:40551,61650:40552,61651:40553,61652:40554,61653:40555,61654:40556,61655:40561,61656:40557,61657:40563,61658:30098,61659:30100,61660:30102,61661:30112,61662:30109,61663:30124,61664:30115,61665:30131,61666:30132,61667:30136,61668:30148,61669:30129,61670:30128,61671:30147,61672:30146,61673:30166,61674:30157,61675:30179,61676:30184,61677:30182,61678:30180,61679:30187,61680:30183,61681:30211,61682:30193,61683:30204,61684:30207,61685:30224,61686:30208,61687:30213,61688:30220,61689:30231,61690:30218,61691:30245,61692:30232,61693:30229,61694:30233,61760:39308,61761:39310,61762:39322,61763:39323,61764:39324,61765:39325,61766:39326,61767:39327,61768:39328,61769:39329,61770:39330,61771:39331,61772:39332,61773:39334,61774:39335,61775:39337,61776:39338,61777:39339,61778:39340,61779:39341,61780:39342,61781:39343,61782:39344,61783:39345,61784:39346,61785:39347,61786:39348,61787:39349,61788:39350,61789:39351,61790:39352,61791:39353,61792:39354,61793:39355,61794:39356,61795:39357,61796:39358,61797:39359,61798:39360,61799:39361,61800:39362,61801:39363,61802:39364,61803:39365,61804:39366,61805:39367,61806:39368,61807:39369,61808:39370,61809:39371,61810:39372,61811:39373,61812:39374,61813:39375,61814:39376,61815:39377,61816:39378,61817:39379,61818:39380,61819:39381,61820:39382,61821:39383,61822:39384,61824:39385,61825:39386,61826:39387,61827:39388,61828:39389,61829:39390,61830:39391,61831:39392,61832:39393,61833:39394,61834:39395,61835:39396,61836:39397,61837:39398,61838:39399,61839:39400,61840:39401,61841:39402,61842:39403,61843:39404,61844:39405,61845:39406,61846:39407,61847:39408,61848:39409,61849:39410,61850:39411,61851:39412,61852:39413,61853:39414,61854:39415,61855:39416,61856:39417,61857:30235,61858:30268,61859:30242,61860:30240,61861:30272,61862:30253,61863:30256,61864:30271,61865:30261,61866:30275,61867:30270,61868:30259,61869:30285,61870:30302,61871:30292,61872:30300,61873:30294,61874:30315,61875:30319,61876:32714,61877:31462,61878:31352,61879:31353,61880:31360,61881:31366,61882:31368,61883:31381,61884:31398,61885:31392,61886:31404,61887:31400,61888:31405,61889:31411,61890:34916,61891:34921,61892:34930,61893:34941,61894:34943,61895:34946,61896:34978,61897:35014,61898:34999,61899:35004,61900:35017,61901:35042,61902:35022,61903:35043,61904:35045,61905:35057,61906:35098,61907:35068,61908:35048,61909:35070,61910:35056,61911:35105,61912:35097,61913:35091,61914:35099,61915:35082,61916:35124,61917:35115,61918:35126,61919:35137,61920:35174,61921:35195,61922:30091,61923:32997,61924:30386,61925:30388,61926:30684,61927:32786,61928:32788,61929:32790,61930:32796,61931:32800,61932:32802,61933:32805,61934:32806,61935:32807,61936:32809,61937:32808,61938:32817,61939:32779,61940:32821,61941:32835,61942:32838,61943:32845,61944:32850,61945:32873,61946:32881,61947:35203,61948:39032,61949:39040,61950:39043,62016:39418,62017:39419,62018:39420,62019:39421,62020:39422,62021:39423,62022:39424,62023:39425,62024:39426,62025:39427,62026:39428,62027:39429,62028:39430,62029:39431,62030:39432,62031:39433,62032:39434,62033:39435,62034:39436,62035:39437,62036:39438,62037:39439,62038:39440,62039:39441,62040:39442,62041:39443,62042:39444,62043:39445,62044:39446,62045:39447,62046:39448,62047:39449,62048:39450,62049:39451,62050:39452,62051:39453,62052:39454,62053:39455,62054:39456,62055:39457,62056:39458,62057:39459,62058:39460,62059:39461,62060:39462,62061:39463,62062:39464,62063:39465,62064:39466,62065:39467,62066:39468,62067:39469,62068:39470,62069:39471,62070:39472,62071:39473,62072:39474,62073:39475,62074:39476,62075:39477,62076:39478,62077:39479,62078:39480,62080:39481,62081:39482,62082:39483,62083:39484,62084:39485,62085:39486,62086:39487,62087:39488,62088:39489,62089:39490,62090:39491,62091:39492,62092:39493,62093:39494,62094:39495,62095:39496,62096:39497,62097:39498,62098:39499,62099:39500,62100:39501,62101:39502,62102:39503,62103:39504,62104:39505,62105:39506,62106:39507,62107:39508,62108:39509,62109:39510,62110:39511,62111:39512,62112:39513,62113:39049,62114:39052,62115:39053,62116:39055,62117:39060,62118:39066,62119:39067,62120:39070,62121:39071,62122:39073,62123:39074,62124:39077,62125:39078,62126:34381,62127:34388,62128:34412,62129:34414,62130:34431,62131:34426,62132:34428,62133:34427,62134:34472,62135:34445,62136:34443,62137:34476,62138:34461,62139:34471,62140:34467,62141:34474,62142:34451,62143:34473,62144:34486,62145:34500,62146:34485,62147:34510,62148:34480,62149:34490,62150:34481,62151:34479,62152:34505,62153:34511,62154:34484,62155:34537,62156:34545,62157:34546,62158:34541,62159:34547,62160:34512,62161:34579,62162:34526,62163:34548,62164:34527,62165:34520,62166:34513,62167:34563,62168:34567,62169:34552,62170:34568,62171:34570,62172:34573,62173:34569,62174:34595,62175:34619,62176:34590,62177:34597,62178:34606,62179:34586,62180:34622,62181:34632,62182:34612,62183:34609,62184:34601,62185:34615,62186:34623,62187:34690,62188:34594,62189:34685,62190:34686,62191:34683,62192:34656,62193:34672,62194:34636,62195:34670,62196:34699,62197:34643,62198:34659,62199:34684,62200:34660,62201:34649,62202:34661,62203:34707,62204:34735,62205:34728,62206:34770,62272:39514,62273:39515,62274:39516,62275:39517,62276:39518,62277:39519,62278:39520,62279:39521,62280:39522,62281:39523,62282:39524,62283:39525,62284:39526,62285:39527,62286:39528,62287:39529,62288:39530,62289:39531,62290:39538,62291:39555,62292:39561,62293:39565,62294:39566,62295:39572,62296:39573,62297:39577,62298:39590,62299:39593,62300:39594,62301:39595,62302:39596,62303:39597,62304:39598,62305:39599,62306:39602,62307:39603,62308:39604,62309:39605,62310:39609,62311:39611,62312:39613,62313:39614,62314:39615,62315:39619,62316:39620,62317:39622,62318:39623,62319:39624,62320:39625,62321:39626,62322:39629,62323:39630,62324:39631,62325:39632,62326:39634,62327:39636,62328:39637,62329:39638,62330:39639,62331:39641,62332:39642,62333:39643,62334:39644,62336:39645,62337:39646,62338:39648,62339:39650,62340:39651,62341:39652,62342:39653,62343:39655,62344:39656,62345:39657,62346:39658,62347:39660,62348:39662,62349:39664,62350:39665,62351:39666,62352:39667,62353:39668,62354:39669,62355:39670,62356:39671,62357:39672,62358:39674,62359:39676,62360:39677,62361:39678,62362:39679,62363:39680,62364:39681,62365:39682,62366:39684,62367:39685,62368:39686,62369:34758,62370:34696,62371:34693,62372:34733,62373:34711,62374:34691,62375:34731,62376:34789,62377:34732,62378:34741,62379:34739,62380:34763,62381:34771,62382:34749,62383:34769,62384:34752,62385:34762,62386:34779,62387:34794,62388:34784,62389:34798,62390:34838,62391:34835,62392:34814,62393:34826,62394:34843,62395:34849,62396:34873,62397:34876,62398:32566,62399:32578,62400:32580,62401:32581,62402:33296,62403:31482,62404:31485,62405:31496,62406:31491,62407:31492,62408:31509,62409:31498,62410:31531,62411:31503,62412:31559,62413:31544,62414:31530,62415:31513,62416:31534,62417:31537,62418:31520,62419:31525,62420:31524,62421:31539,62422:31550,62423:31518,62424:31576,62425:31578,62426:31557,62427:31605,62428:31564,62429:31581,62430:31584,62431:31598,62432:31611,62433:31586,62434:31602,62435:31601,62436:31632,62437:31654,62438:31655,62439:31672,62440:31660,62441:31645,62442:31656,62443:31621,62444:31658,62445:31644,62446:31650,62447:31659,62448:31668,62449:31697,62450:31681,62451:31692,62452:31709,62453:31706,62454:31717,62455:31718,62456:31722,62457:31756,62458:31742,62459:31740,62460:31759,62461:31766,62462:31755,62528:39687,62529:39689,62530:39690,62531:39691,62532:39692,62533:39693,62534:39694,62535:39696,62536:39697,62537:39698,62538:39700,62539:39701,62540:39702,62541:39703,62542:39704,62543:39705,62544:39706,62545:39707,62546:39708,62547:39709,62548:39710,62549:39712,62550:39713,62551:39714,62552:39716,62553:39717,62554:39718,62555:39719,62556:39720,62557:39721,62558:39722,62559:39723,62560:39724,62561:39725,62562:39726,62563:39728,62564:39729,62565:39731,62566:39732,62567:39733,62568:39734,62569:39735,62570:39736,62571:39737,62572:39738,62573:39741,62574:39742,62575:39743,62576:39744,62577:39750,62578:39754,62579:39755,62580:39756,62581:39758,62582:39760,62583:39762,62584:39763,62585:39765,62586:39766,62587:39767,62588:39768,62589:39769,62590:39770,62592:39771,62593:39772,62594:39773,62595:39774,62596:39775,62597:39776,62598:39777,62599:39778,62600:39779,62601:39780,62602:39781,62603:39782,62604:39783,62605:39784,62606:39785,62607:39786,62608:39787,62609:39788,62610:39789,62611:39790,62612:39791,62613:39792,62614:39793,62615:39794,62616:39795,62617:39796,62618:39797,62619:39798,62620:39799,62621:39800,62622:39801,62623:39802,62624:39803,62625:31775,62626:31786,62627:31782,62628:31800,62629:31809,62630:31808,62631:33278,62632:33281,62633:33282,62634:33284,62635:33260,62636:34884,62637:33313,62638:33314,62639:33315,62640:33325,62641:33327,62642:33320,62643:33323,62644:33336,62645:33339,62646:33331,62647:33332,62648:33342,62649:33348,62650:33353,62651:33355,62652:33359,62653:33370,62654:33375,62655:33384,62656:34942,62657:34949,62658:34952,62659:35032,62660:35039,62661:35166,62662:32669,62663:32671,62664:32679,62665:32687,62666:32688,62667:32690,62668:31868,62669:25929,62670:31889,62671:31901,62672:31900,62673:31902,62674:31906,62675:31922,62676:31932,62677:31933,62678:31937,62679:31943,62680:31948,62681:31949,62682:31944,62683:31941,62684:31959,62685:31976,62686:33390,62687:26280,62688:32703,62689:32718,62690:32725,62691:32741,62692:32737,62693:32742,62694:32745,62695:32750,62696:32755,62697:31992,62698:32119,62699:32166,62700:32174,62701:32327,62702:32411,62703:40632,62704:40628,62705:36211,62706:36228,62707:36244,62708:36241,62709:36273,62710:36199,62711:36205,62712:35911,62713:35913,62714:37194,62715:37200,62716:37198,62717:37199,62718:37220,62784:39804,62785:39805,62786:39806,62787:39807,62788:39808,62789:39809,62790:39810,62791:39811,62792:39812,62793:39813,62794:39814,62795:39815,62796:39816,62797:39817,62798:39818,62799:39819,62800:39820,62801:39821,62802:39822,62803:39823,62804:39824,62805:39825,62806:39826,62807:39827,62808:39828,62809:39829,62810:39830,62811:39831,62812:39832,62813:39833,62814:39834,62815:39835,62816:39836,62817:39837,62818:39838,62819:39839,62820:39840,62821:39841,62822:39842,62823:39843,62824:39844,62825:39845,62826:39846,62827:39847,62828:39848,62829:39849,62830:39850,62831:39851,62832:39852,62833:39853,62834:39854,62835:39855,62836:39856,62837:39857,62838:39858,62839:39859,62840:39860,62841:39861,62842:39862,62843:39863,62844:39864,62845:39865,62846:39866,62848:39867,62849:39868,62850:39869,62851:39870,62852:39871,62853:39872,62854:39873,62855:39874,62856:39875,62857:39876,62858:39877,62859:39878,62860:39879,62861:39880,62862:39881,62863:39882,62864:39883,62865:39884,62866:39885,62867:39886,62868:39887,62869:39888,62870:39889,62871:39890,62872:39891,62873:39892,62874:39893,62875:39894,62876:39895,62877:39896,62878:39897,62879:39898,62880:39899,62881:37218,62882:37217,62883:37232,62884:37225,62885:37231,62886:37245,62887:37246,62888:37234,62889:37236,62890:37241,62891:37260,62892:37253,62893:37264,62894:37261,62895:37265,62896:37282,62897:37283,62898:37290,62899:37293,62900:37294,62901:37295,62902:37301,62903:37300,62904:37306,62905:35925,62906:40574,62907:36280,62908:36331,62909:36357,62910:36441,62911:36457,62912:36277,62913:36287,62914:36284,62915:36282,62916:36292,62917:36310,62918:36311,62919:36314,62920:36318,62921:36302,62922:36303,62923:36315,62924:36294,62925:36332,62926:36343,62927:36344,62928:36323,62929:36345,62930:36347,62931:36324,62932:36361,62933:36349,62934:36372,62935:36381,62936:36383,62937:36396,62938:36398,62939:36387,62940:36399,62941:36410,62942:36416,62943:36409,62944:36405,62945:36413,62946:36401,62947:36425,62948:36417,62949:36418,62950:36433,62951:36434,62952:36426,62953:36464,62954:36470,62955:36476,62956:36463,62957:36468,62958:36485,62959:36495,62960:36500,62961:36496,62962:36508,62963:36510,62964:35960,62965:35970,62966:35978,62967:35973,62968:35992,62969:35988,62970:26011,62971:35286,62972:35294,62973:35290,62974:35292,63040:39900,63041:39901,63042:39902,63043:39903,63044:39904,63045:39905,63046:39906,63047:39907,63048:39908,63049:39909,63050:39910,63051:39911,63052:39912,63053:39913,63054:39914,63055:39915,63056:39916,63057:39917,63058:39918,63059:39919,63060:39920,63061:39921,63062:39922,63063:39923,63064:39924,63065:39925,63066:39926,63067:39927,63068:39928,63069:39929,63070:39930,63071:39931,63072:39932,63073:39933,63074:39934,63075:39935,63076:39936,63077:39937,63078:39938,63079:39939,63080:39940,63081:39941,63082:39942,63083:39943,63084:39944,63085:39945,63086:39946,63087:39947,63088:39948,63089:39949,63090:39950,63091:39951,63092:39952,63093:39953,63094:39954,63095:39955,63096:39956,63097:39957,63098:39958,63099:39959,63100:39960,63101:39961,63102:39962,63104:39963,63105:39964,63106:39965,63107:39966,63108:39967,63109:39968,63110:39969,63111:39970,63112:39971,63113:39972,63114:39973,63115:39974,63116:39975,63117:39976,63118:39977,63119:39978,63120:39979,63121:39980,63122:39981,63123:39982,63124:39983,63125:39984,63126:39985,63127:39986,63128:39987,63129:39988,63130:39989,63131:39990,63132:39991,63133:39992,63134:39993,63135:39994,63136:39995,63137:35301,63138:35307,63139:35311,63140:35390,63141:35622,63142:38739,63143:38633,63144:38643,63145:38639,63146:38662,63147:38657,63148:38664,63149:38671,63150:38670,63151:38698,63152:38701,63153:38704,63154:38718,63155:40832,63156:40835,63157:40837,63158:40838,63159:40839,63160:40840,63161:40841,63162:40842,63163:40844,63164:40702,63165:40715,63166:40717,63167:38585,63168:38588,63169:38589,63170:38606,63171:38610,63172:30655,63173:38624,63174:37518,63175:37550,63176:37576,63177:37694,63178:37738,63179:37834,63180:37775,63181:37950,63182:37995,63183:40063,63184:40066,63185:40069,63186:40070,63187:40071,63188:40072,63189:31267,63190:40075,63191:40078,63192:40080,63193:40081,63194:40082,63195:40084,63196:40085,63197:40090,63198:40091,63199:40094,63200:40095,63201:40096,63202:40097,63203:40098,63204:40099,63205:40101,63206:40102,63207:40103,63208:40104,63209:40105,63210:40107,63211:40109,63212:40110,63213:40112,63214:40113,63215:40114,63216:40115,63217:40116,63218:40117,63219:40118,63220:40119,63221:40122,63222:40123,63223:40124,63224:40125,63225:40132,63226:40133,63227:40134,63228:40135,63229:40138,63230:40139,63296:39996,63297:39997,63298:39998,63299:39999,63300:40000,63301:40001,63302:40002,63303:40003,63304:40004,63305:40005,63306:40006,63307:40007,63308:40008,63309:40009,63310:40010,63311:40011,63312:40012,63313:40013,63314:40014,63315:40015,63316:40016,63317:40017,63318:40018,63319:40019,63320:40020,63321:40021,63322:40022,63323:40023,63324:40024,63325:40025,63326:40026,63327:40027,63328:40028,63329:40029,63330:40030,63331:40031,63332:40032,63333:40033,63334:40034,63335:40035,63336:40036,63337:40037,63338:40038,63339:40039,63340:40040,63341:40041,63342:40042,63343:40043,63344:40044,63345:40045,63346:40046,63347:40047,63348:40048,63349:40049,63350:40050,63351:40051,63352:40052,63353:40053,63354:40054,63355:40055,63356:40056,63357:40057,63358:40058,63360:40059,63361:40061,63362:40062,63363:40064,63364:40067,63365:40068,63366:40073,63367:40074,63368:40076,63369:40079,63370:40083,63371:40086,63372:40087,63373:40088,63374:40089,63375:40093,63376:40106,63377:40108,63378:40111,63379:40121,63380:40126,63381:40127,63382:40128,63383:40129,63384:40130,63385:40136,63386:40137,63387:40145,63388:40146,63389:40154,63390:40155,63391:40160,63392:40161,63393:40140,63394:40141,63395:40142,63396:40143,63397:40144,63398:40147,63399:40148,63400:40149,63401:40151,63402:40152,63403:40153,63404:40156,63405:40157,63406:40159,63407:40162,63408:38780,63409:38789,63410:38801,63411:38802,63412:38804,63413:38831,63414:38827,63415:38819,63416:38834,63417:38836,63418:39601,63419:39600,63420:39607,63421:40536,63422:39606,63423:39610,63424:39612,63425:39617,63426:39616,63427:39621,63428:39618,63429:39627,63430:39628,63431:39633,63432:39749,63433:39747,63434:39751,63435:39753,63436:39752,63437:39757,63438:39761,63439:39144,63440:39181,63441:39214,63442:39253,63443:39252,63444:39647,63445:39649,63446:39654,63447:39663,63448:39659,63449:39675,63450:39661,63451:39673,63452:39688,63453:39695,63454:39699,63455:39711,63456:39715,63457:40637,63458:40638,63459:32315,63460:40578,63461:40583,63462:40584,63463:40587,63464:40594,63465:37846,63466:40605,63467:40607,63468:40667,63469:40668,63470:40669,63471:40672,63472:40671,63473:40674,63474:40681,63475:40679,63476:40677,63477:40682,63478:40687,63479:40738,63480:40748,63481:40751,63482:40761,63483:40759,63484:40765,63485:40766,63486:40772,63552:40163,63553:40164,63554:40165,63555:40166,63556:40167,63557:40168,63558:40169,63559:40170,63560:40171,63561:40172,63562:40173,63563:40174,63564:40175,63565:40176,63566:40177,63567:40178,63568:40179,63569:40180,63570:40181,63571:40182,63572:40183,63573:40184,63574:40185,63575:40186,63576:40187,63577:40188,63578:40189,63579:40190,63580:40191,63581:40192,63582:40193,63583:40194,63584:40195,63585:40196,63586:40197,63587:40198,63588:40199,63589:40200,63590:40201,63591:40202,63592:40203,63593:40204,63594:40205,63595:40206,63596:40207,63597:40208,63598:40209,63599:40210,63600:40211,63601:40212,63602:40213,63603:40214,63604:40215,63605:40216,63606:40217,63607:40218,63608:40219,63609:40220,63610:40221,63611:40222,63612:40223,63613:40224,63614:40225,63616:40226,63617:40227,63618:40228,63619:40229,63620:40230,63621:40231,63622:40232,63623:40233,63624:40234,63625:40235,63626:40236,63627:40237,63628:40238,63629:40239,63630:40240,63631:40241,63632:40242,63633:40243,63634:40244,63635:40245,63636:40246,63637:40247,63638:40248,63639:40249,63640:40250,63641:40251,63642:40252,63643:40253,63644:40254,63645:40255,63646:40256,63647:40257,63648:40258,63649:57908,63650:57909,63651:57910,63652:57911,63653:57912,63654:57913,63655:57914,63656:57915,63657:57916,63658:57917,63659:57918,63660:57919,63661:57920,63662:57921,63663:57922,63664:57923,63665:57924,63666:57925,63667:57926,63668:57927,63669:57928,63670:57929,63671:57930,63672:57931,63673:57932,63674:57933,63675:57934,63676:57935,63677:57936,63678:57937,63679:57938,63680:57939,63681:57940,63682:57941,63683:57942,63684:57943,63685:57944,63686:57945,63687:57946,63688:57947,63689:57948,63690:57949,63691:57950,63692:57951,63693:57952,63694:57953,63695:57954,63696:57955,63697:57956,63698:57957,63699:57958,63700:57959,63701:57960,63702:57961,63703:57962,63704:57963,63705:57964,63706:57965,63707:57966,63708:57967,63709:57968,63710:57969,63711:57970,63712:57971,63713:57972,63714:57973,63715:57974,63716:57975,63717:57976,63718:57977,63719:57978,63720:57979,63721:57980,63722:57981,63723:57982,63724:57983,63725:57984,63726:57985,63727:57986,63728:57987,63729:57988,63730:57989,63731:57990,63732:57991,63733:57992,63734:57993,63735:57994,63736:57995,63737:57996,63738:57997,63739:57998,63740:57999,63741:58000,63742:58001,63808:40259,63809:40260,63810:40261,63811:40262,63812:40263,63813:40264,63814:40265,63815:40266,63816:40267,63817:40268,63818:40269,63819:40270,63820:40271,63821:40272,63822:40273,63823:40274,63824:40275,63825:40276,63826:40277,63827:40278,63828:40279,63829:40280,63830:40281,63831:40282,63832:40283,63833:40284,63834:40285,63835:40286,63836:40287,63837:40288,63838:40289,63839:40290,63840:40291,63841:40292,63842:40293,63843:40294,63844:40295,63845:40296,63846:40297,63847:40298,63848:40299,63849:40300,63850:40301,63851:40302,63852:40303,63853:40304,63854:40305,63855:40306,63856:40307,63857:40308,63858:40309,63859:40310,63860:40311,63861:40312,63862:40313,63863:40314,63864:40315,63865:40316,63866:40317,63867:40318,63868:40319,63869:40320,63870:40321,63872:40322,63873:40323,63874:40324,63875:40325,63876:40326,63877:40327,63878:40328,63879:40329,63880:40330,63881:40331,63882:40332,63883:40333,63884:40334,63885:40335,63886:40336,63887:40337,63888:40338,63889:40339,63890:40340,63891:40341,63892:40342,63893:40343,63894:40344,63895:40345,63896:40346,63897:40347,63898:40348,63899:40349,63900:40350,63901:40351,63902:40352,63903:40353,63904:40354,63905:58002,63906:58003,63907:58004,63908:58005,63909:58006,63910:58007,63911:58008,63912:58009,63913:58010,63914:58011,63915:58012,63916:58013,63917:58014,63918:58015,63919:58016,63920:58017,63921:58018,63922:58019,63923:58020,63924:58021,63925:58022,63926:58023,63927:58024,63928:58025,63929:58026,63930:58027,63931:58028,63932:58029,63933:58030,63934:58031,63935:58032,63936:58033,63937:58034,63938:58035,63939:58036,63940:58037,63941:58038,63942:58039,63943:58040,63944:58041,63945:58042,63946:58043,63947:58044,63948:58045,63949:58046,63950:58047,63951:58048,63952:58049,63953:58050,63954:58051,63955:58052,63956:58053,63957:58054,63958:58055,63959:58056,63960:58057,63961:58058,63962:58059,63963:58060,63964:58061,63965:58062,63966:58063,63967:58064,63968:58065,63969:58066,63970:58067,63971:58068,63972:58069,63973:58070,63974:58071,63975:58072,63976:58073,63977:58074,63978:58075,63979:58076,63980:58077,63981:58078,63982:58079,63983:58080,63984:58081,63985:58082,63986:58083,63987:58084,63988:58085,63989:58086,63990:58087,63991:58088,63992:58089,63993:58090,63994:58091,63995:58092,63996:58093,63997:58094,63998:58095,64064:40355,64065:40356,64066:40357,64067:40358,64068:40359,64069:40360,64070:40361,64071:40362,64072:40363,64073:40364,64074:40365,64075:40366,64076:40367,64077:40368,64078:40369,64079:40370,64080:40371,64081:40372,64082:40373,64083:40374,64084:40375,64085:40376,64086:40377,64087:40378,64088:40379,64089:40380,64090:40381,64091:40382,64092:40383,64093:40384,64094:40385,64095:40386,64096:40387,64097:40388,64098:40389,64099:40390,64100:40391,64101:40392,64102:40393,64103:40394,64104:40395,64105:40396,64106:40397,64107:40398,64108:40399,64109:40400,64110:40401,64111:40402,64112:40403,64113:40404,64114:40405,64115:40406,64116:40407,64117:40408,64118:40409,64119:40410,64120:40411,64121:40412,64122:40413,64123:40414,64124:40415,64125:40416,64126:40417,64128:40418,64129:40419,64130:40420,64131:40421,64132:40422,64133:40423,64134:40424,64135:40425,64136:40426,64137:40427,64138:40428,64139:40429,64140:40430,64141:40431,64142:40432,64143:40433,64144:40434,64145:40435,64146:40436,64147:40437,64148:40438,64149:40439,64150:40440,64151:40441,64152:40442,64153:40443,64154:40444,64155:40445,64156:40446,64157:40447,64158:40448,64159:40449,64160:40450,64161:58096,64162:58097,64163:58098,64164:58099,64165:58100,64166:58101,64167:58102,64168:58103,64169:58104,64170:58105,64171:58106,64172:58107,64173:58108,64174:58109,64175:58110,64176:58111,64177:58112,64178:58113,64179:58114,64180:58115,64181:58116,64182:58117,64183:58118,64184:58119,64185:58120,64186:58121,64187:58122,64188:58123,64189:58124,64190:58125,64191:58126,64192:58127,64193:58128,64194:58129,64195:58130,64196:58131,64197:58132,64198:58133,64199:58134,64200:58135,64201:58136,64202:58137,64203:58138,64204:58139,64205:58140,64206:58141,64207:58142,64208:58143,64209:58144,64210:58145,64211:58146,64212:58147,64213:58148,64214:58149,64215:58150,64216:58151,64217:58152,64218:58153,64219:58154,64220:58155,64221:58156,64222:58157,64223:58158,64224:58159,64225:58160,64226:58161,64227:58162,64228:58163,64229:58164,64230:58165,64231:58166,64232:58167,64233:58168,64234:58169,64235:58170,64236:58171,64237:58172,64238:58173,64239:58174,64240:58175,64241:58176,64242:58177,64243:58178,64244:58179,64245:58180,64246:58181,64247:58182,64248:58183,64249:58184,64250:58185,64251:58186,64252:58187,64253:58188,64254:58189,64320:40451,64321:40452,64322:40453,64323:40454,64324:40455,64325:40456,64326:40457,64327:40458,64328:40459,64329:40460,64330:40461,64331:40462,64332:40463,64333:40464,64334:40465,64335:40466,64336:40467,64337:40468,64338:40469,64339:40470,64340:40471,64341:40472,64342:40473,64343:40474,64344:40475,64345:40476,64346:40477,64347:40478,64348:40484,64349:40487,64350:40494,64351:40496,64352:40500,64353:40507,64354:40508,64355:40512,64356:40525,64357:40528,64358:40530,64359:40531,64360:40532,64361:40534,64362:40537,64363:40541,64364:40543,64365:40544,64366:40545,64367:40546,64368:40549,64369:40558,64370:40559,64371:40562,64372:40564,64373:40565,64374:40566,64375:40567,64376:40568,64377:40569,64378:40570,64379:40571,64380:40572,64381:40573,64382:40576,64384:40577,64385:40579,64386:40580,64387:40581,64388:40582,64389:40585,64390:40586,64391:40588,64392:40589,64393:40590,64394:40591,64395:40592,64396:40593,64397:40596,64398:40597,64399:40598,64400:40599,64401:40600,64402:40601,64403:40602,64404:40603,64405:40604,64406:40606,64407:40608,64408:40609,64409:40610,64410:40611,64411:40612,64412:40613,64413:40615,64414:40616,64415:40617,64416:40618,64417:58190,64418:58191,64419:58192,64420:58193,64421:58194,64422:58195,64423:58196,64424:58197,64425:58198,64426:58199,64427:58200,64428:58201,64429:58202,64430:58203,64431:58204,64432:58205,64433:58206,64434:58207,64435:58208,64436:58209,64437:58210,64438:58211,64439:58212,64440:58213,64441:58214,64442:58215,64443:58216,64444:58217,64445:58218,64446:58219,64447:58220,64448:58221,64449:58222,64450:58223,64451:58224,64452:58225,64453:58226,64454:58227,64455:58228,64456:58229,64457:58230,64458:58231,64459:58232,64460:58233,64461:58234,64462:58235,64463:58236,64464:58237,64465:58238,64466:58239,64467:58240,64468:58241,64469:58242,64470:58243,64471:58244,64472:58245,64473:58246,64474:58247,64475:58248,64476:58249,64477:58250,64478:58251,64479:58252,64480:58253,64481:58254,64482:58255,64483:58256,64484:58257,64485:58258,64486:58259,64487:58260,64488:58261,64489:58262,64490:58263,64491:58264,64492:58265,64493:58266,64494:58267,64495:58268,64496:58269,64497:58270,64498:58271,64499:58272,64500:58273,64501:58274,64502:58275,64503:58276,64504:58277,64505:58278,64506:58279,64507:58280,64508:58281,64509:58282,64510:58283,64576:40619,64577:40620,64578:40621,64579:40622,64580:40623,64581:40624,64582:40625,64583:40626,64584:40627,64585:40629,64586:40630,64587:40631,64588:40633,64589:40634,64590:40636,64591:40639,64592:40640,64593:40641,64594:40642,64595:40643,64596:40645,64597:40646,64598:40647,64599:40648,64600:40650,64601:40651,64602:40652,64603:40656,64604:40658,64605:40659,64606:40661,64607:40662,64608:40663,64609:40665,64610:40666,64611:40670,64612:40673,64613:40675,64614:40676,64615:40678,64616:40680,64617:40683,64618:40684,64619:40685,64620:40686,64621:40688,64622:40689,64623:40690,64624:40691,64625:40692,64626:40693,64627:40694,64628:40695,64629:40696,64630:40698,64631:40701,64632:40703,64633:40704,64634:40705,64635:40706,64636:40707,64637:40708,64638:40709,64640:40710,64641:40711,64642:40712,64643:40713,64644:40714,64645:40716,64646:40719,64647:40721,64648:40722,64649:40724,64650:40725,64651:40726,64652:40728,64653:40730,64654:40731,64655:40732,64656:40733,64657:40734,64658:40735,64659:40737,64660:40739,64661:40740,64662:40741,64663:40742,64664:40743,64665:40744,64666:40745,64667:40746,64668:40747,64669:40749,64670:40750,64671:40752,64672:40753,64673:58284,64674:58285,64675:58286,64676:58287,64677:58288,64678:58289,64679:58290,64680:58291,64681:58292,64682:58293,64683:58294,64684:58295,64685:58296,64686:58297,64687:58298,64688:58299,64689:58300,64690:58301,64691:58302,64692:58303,64693:58304,64694:58305,64695:58306,64696:58307,64697:58308,64698:58309,64699:58310,64700:58311,64701:58312,64702:58313,64703:58314,64704:58315,64705:58316,64706:58317,64707:58318,64708:58319,64709:58320,64710:58321,64711:58322,64712:58323,64713:58324,64714:58325,64715:58326,64716:58327,64717:58328,64718:58329,64719:58330,64720:58331,64721:58332,64722:58333,64723:58334,64724:58335,64725:58336,64726:58337,64727:58338,64728:58339,64729:58340,64730:58341,64731:58342,64732:58343,64733:58344,64734:58345,64735:58346,64736:58347,64737:58348,64738:58349,64739:58350,64740:58351,64741:58352,64742:58353,64743:58354,64744:58355,64745:58356,64746:58357,64747:58358,64748:58359,64749:58360,64750:58361,64751:58362,64752:58363,64753:58364,64754:58365,64755:58366,64756:58367,64757:58368,64758:58369,64759:58370,64760:58371,64761:58372,64762:58373,64763:58374,64764:58375,64765:58376,64766:58377,64832:40754,64833:40755,64834:40756,64835:40757,64836:40758,64837:40760,64838:40762,64839:40764,64840:40767,64841:40768,64842:40769,64843:40770,64844:40771,64845:40773,64846:40774,64847:40775,64848:40776,64849:40777,64850:40778,64851:40779,64852:40780,64853:40781,64854:40782,64855:40783,64856:40786,64857:40787,64858:40788,64859:40789,64860:40790,64861:40791,64862:40792,64863:40793,64864:40794,64865:40795,64866:40796,64867:40797,64868:40798,64869:40799,64870:40800,64871:40801,64872:40802,64873:40803,64874:40804,64875:40805,64876:40806,64877:40807,64878:40808,64879:40809,64880:40810,64881:40811,64882:40812,64883:40813,64884:40814,64885:40815,64886:40816,64887:40817,64888:40818,64889:40819,64890:40820,64891:40821,64892:40822,64893:40823,64894:40824,64896:40825,64897:40826,64898:40827,64899:40828,64900:40829,64901:40830,64902:40833,64903:40834,64904:40845,64905:40846,64906:40847,64907:40848,64908:40849,64909:40850,64910:40851,64911:40852,64912:40853,64913:40854,64914:40855,64915:40856,64916:40860,64917:40861,64918:40862,64919:40865,64920:40866,64921:40867,64922:40868,64923:40869,64924:63788,64925:63865,64926:63893,64927:63975,64928:63985,64929:58378,64930:58379,64931:58380,64932:58381,64933:58382,64934:58383,64935:58384,64936:58385,64937:58386,64938:58387,64939:58388,64940:58389,64941:58390,64942:58391,64943:58392,64944:58393,64945:58394,64946:58395,64947:58396,64948:58397,64949:58398,64950:58399,64951:58400,64952:58401,64953:58402,64954:58403,64955:58404,64956:58405,64957:58406,64958:58407,64959:58408,64960:58409,64961:58410,64962:58411,64963:58412,64964:58413,64965:58414,64966:58415,64967:58416,64968:58417,64969:58418,64970:58419,64971:58420,64972:58421,64973:58422,64974:58423,64975:58424,64976:58425,64977:58426,64978:58427,64979:58428,64980:58429,64981:58430,64982:58431,64983:58432,64984:58433,64985:58434,64986:58435,64987:58436,64988:58437,64989:58438,64990:58439,64991:58440,64992:58441,64993:58442,64994:58443,64995:58444,64996:58445,64997:58446,64998:58447,64999:58448,65000:58449,65001:58450,65002:58451,65003:58452,65004:58453,65005:58454,65006:58455,65007:58456,65008:58457,65009:58458,65010:58459,65011:58460,65012:58461,65013:58462,65014:58463,65015:58464,65016:58465,65017:58466,65018:58467,65019:58468,65020:58469,65021:58470,65022:58471,65088:64012,65089:64013,65090:64014,65091:64015,65092:64017,65093:64019,65094:64020,65095:64024,65096:64031,65097:64032,65098:64033,65099:64035,65100:64036,65101:64039,65102:64040,65103:64041,65104:11905,65105:59414,65106:59415,65107:59416,65108:11908,65109:13427,65110:13383,65111:11912,65112:11915,65113:59422,65114:13726,65115:13850,65116:13838,65117:11916,65118:11927,65119:14702,65120:14616,65121:59430,65122:14799,65123:14815,65124:14963,65125:14800,65126:59435,65127:59436,65128:15182,65129:15470,65130:15584,65131:11943,65132:59441,65133:59442,65134:11946,65135:16470,65136:16735,65137:11950,65138:17207,65139:11955,65140:11958,65141:11959,65142:59451,65143:17329,65144:17324,65145:11963,65146:17373,65147:17622,65148:18017,65149:17996,65150:59459,65152:18211,65153:18217,65154:18300,65155:18317,65156:11978,65157:18759,65158:18810,65159:18813,65160:18818,65161:18819,65162:18821,65163:18822,65164:18847,65165:18843,65166:18871,65167:18870,65168:59476,65169:59477,65170:19619,65171:19615,65172:19616,65173:19617,65174:19575,65175:19618,65176:19731,65177:19732,65178:19733,65179:19734,65180:19735,65181:19736,65182:19737,65183:19886,65184:59492,65185:58472,65186:58473,65187:58474,65188:58475,65189:58476,65190:58477,65191:58478,65192:58479,65193:58480,65194:58481,65195:58482,65196:58483,65197:58484,65198:58485,65199:58486,65200:58487,65201:58488,65202:58489,65203:58490,65204:58491,65205:58492,65206:58493,65207:58494,65208:58495,65209:58496,65210:58497,65211:58498,65212:58499,65213:58500,65214:58501,65215:58502,65216:58503,65217:58504,65218:58505,65219:58506,65220:58507,65221:58508,65222:58509,65223:58510,65224:58511,65225:58512,65226:58513,65227:58514,65228:58515,65229:58516,65230:58517,65231:58518,65232:58519,65233:58520,65234:58521,65235:58522,65236:58523,65237:58524,65238:58525,65239:58526,65240:58527,65241:58528,65242:58529,65243:58530,65244:58531,65245:58532,65246:58533,65247:58534,65248:58535,65249:58536,65250:58537,65251:58538,65252:58539,65253:58540,65254:58541,65255:58542,65256:58543,65257:58544,65258:58545,65259:58546,65260:58547,65261:58548,65262:58549,65263:58550,65264:58551,65265:58552,65266:58553,65267:58554,65268:58555,65269:58556,65270:58557,65271:58558,65272:58559,65273:58560,65274:58561,65275:58562,65276:58563,65277:58564,65278:58565} \ No newline at end of file diff --git a/node_modules/grunt/node_modules/iconv-lite/generation/generate-big5-table.js b/node_modules/grunt/node_modules/iconv-lite/generation/generate-big5-table.js new file mode 100644 index 000000000..909e433a2 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/generation/generate-big5-table.js @@ -0,0 +1,25 @@ +var http = require('http'); +var fs = require('fs'); +// BIG5 +var cp950_b2u = {host:'moztw.org',path:'/docs/big5/table/cp950-b2u.txt'}, + cp950_u2b = {host:'moztw.org',path:'/docs/big5/table/cp950-u2b.txt'}, + cp950_moz18_b2u = {host:'moztw.org',path:'/docs/big5/table/moz18-b2u.txt'}; + +http.get(cp950_moz18_b2u, function(res) { + var data = ''; + res.on('data', function(chunk) { + data += chunk; + }); + res.on('end', function() { + var table = {}; + data = data.split('\n').slice(1); + data.forEach(function(line, idx) { + var pair = line.split(' '); + var key = parseInt(pair[0]); + var val = parseInt(pair[1]); + table[key] = val; + }); + fs.createWriteSync('encodings/table/big5.js', + 'module.exports = ' + JSON.stringify(table) + ';'); + }); +}); diff --git a/node_modules/grunt/node_modules/iconv-lite/generation/generate-singlebyte.js b/node_modules/grunt/node_modules/iconv-lite/generation/generate-singlebyte.js new file mode 100644 index 000000000..2cbebece8 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/generation/generate-singlebyte.js @@ -0,0 +1,142 @@ +var fs = require("fs"); +var Iconv = require("iconv").Iconv; + + +var encodingFamilies = [ + { + // Windows code pages + encodings: [1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258], + convert: function(cp) { + return { + name: "windows-"+cp, + aliases: ["win"+cp, "cp"+cp, ""+cp], + } + } + }, + { + // ISO-8859 code pages + encodings: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16], + convert: function(i) { + return { + name: "iso-8859-"+i, + aliases: ["cp"+(28590+i), (28590+i)], + } + } + }, + { + // IBM/DOS code pages + encodings: [437, 737, 775, 850, 852, 855, 857, 858, 860, 861, 862, 863, 864, 865, 866, 869], + convert: function(cp) { + return { + name: "CP"+cp, + aliases: ["ibm"+cp, ""+cp], + } + } + }, + { + // Macintosh code pages + encodings: ["macCroatian", "macCyrillic", "macGreek", + "macIceland", "macRoman", "macRomania", + "macThai", "macTurkish", "macUkraine"], + }, + { + // KOI8 code pages + encodings: ["KOI8-R", "KOI8-U"], + }, +]; + + +var encodings = { + // Aliases. + "ascii8bit": "ascii", + "usascii": "ascii", + + "latin1": "iso88591", + "latin2": "iso88592", + "latin3": "iso88593", + "latin4": "iso88594", + "latin6": "iso885910", + "latin7": "iso885913", + "latin8": "iso885914", + "latin9": "iso885915", + "latin10": "iso885916", + + "cp819": "iso88951", + "arabic": "iso88596", + "arabic8": "iso88596", + "greek" : "iso88597", + "greek8" : "iso88597", + "hebrew": "iso88598", + "hebrew8": "iso88598", + "turkish": "iso88599", + "turkish8": "iso88599", + "thai": "iso885911", + "thai8": "iso885911", + "tis620": "iso885911", + "windows874": "iso885911", + "win874": "iso885911", + "cp874": "iso885911", + "874": "iso885911", + "celtic": "iso885914", + "celtic8": "iso885914", + + "cp20866": "koi8r", + "20866": "koi8r", + "ibm878": "koi8r", + "cp21866": "koi8u", + "21866": "koi8u", + "ibm1168": "koi8u", + +}; + +// Add all encodings from encodingFamilies. +encodingFamilies.forEach(function(family){ + family.encodings.forEach(function(encoding){ + if (family.convert) + encoding = family.convert(encoding); + + var encodingIconvName = encoding.name ? encoding.name : encoding; + var encodingName = encodingIconvName.replace(/[-_]/g, "").toLowerCase(); + + encodings[encodingName] = { + type: "singlebyte", + chars: generateCharsString(encodingIconvName) + }; + + if (encoding.aliases) + encoding.aliases.forEach(function(alias){ + encodings[alias] = encodingName; + }); + }); +}); + +// Write encodings. +fs.writeFileSync("encodings/singlebyte.js", + "module.exports = " + JSON.stringify(encodings, undefined, " ") + ";"); + + +function generateCharsString(encoding) { + console.log("Generate encoding for " + encoding); + var iconvToUtf8 = new Iconv(encoding, "UTF-8"); + var chars = ""; + + for (var b = 0x80; b < 0x100; b++) { + + try { + var convertedChar = iconvToUtf8.convert(new Buffer([b])).toString(); + + if (convertedChar.length != 1) + throw new Error("Single-byte encoding error: Must return single char."); + } catch (exception) { + if (exception.code === "EILSEQ") { + convertedChar = "\ufffd"; + } else { + throw exception; + } + } + + chars += convertedChar; + } + + return chars; +} diff --git a/node_modules/grunt/node_modules/iconv-lite/index.js b/node_modules/grunt/node_modules/iconv-lite/index.js new file mode 100644 index 000000000..a55691b1e --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/index.js @@ -0,0 +1,231 @@ +var RE_SPACEDASH = /[- ]/g; +// Module exports +var iconv = module.exports = { + toEncoding: function(str, encoding) { + return iconv.getCodec(encoding).toEncoding(str); + }, + fromEncoding: function(buf, encoding) { + return iconv.getCodec(encoding).fromEncoding(buf); + }, + encodingExists: function(enc) { + loadEncodings(); + enc = enc.replace(RE_SPACEDASH, "").toLowerCase(); + return (iconv.encodings[enc] !== undefined); + }, + + defaultCharUnicode: '�', + defaultCharSingleByte: '?', + + encodingsLoaded: false, + + // Get correct codec for given encoding. + getCodec: function(encoding) { + loadEncodings(); + var enc = encoding || "utf8"; + var codecOptions = undefined; + while (1) { + if (getType(enc) === "String") + enc = enc.replace(RE_SPACEDASH, "").toLowerCase(); + var codec = iconv.encodings[enc]; + var type = getType(codec); + if (type === "String") { + // Link to other encoding. + codecOptions = {originalEncoding: enc}; + enc = codec; + } + else if (type === "Object" && codec.type != undefined) { + // Options for other encoding. + codecOptions = codec; + enc = codec.type; + } + else if (type === "Function") + // Codec itself. + return codec(codecOptions); + else + throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')"); + } + }, + + // Define basic encodings + encodings: { + internal: function(options) { + return { + toEncoding: toInternalEncoding, + fromEncoding: fromInternalEncoding, + options: options + }; + }, + utf8: "internal", + ucs2: "internal", + binary: "internal", + ascii: "internal", + base64: "internal", + + // Codepage single-byte encodings. + singlebyte: function(options) { + // Prepare chars if needed + if (!options.charsBuf) { + if (!options.chars || (options.chars.length !== 128 && options.chars.length !== 256)) + throw new Error("Encoding '"+options.type+"' has incorrect 'chars' (must be of len 128 or 256)"); + + if (options.chars.length === 128) + options.chars = asciiString + options.chars; + + options.charsBuf = new Buffer(options.chars, 'ucs2'); + } + + if (!options.revCharsBuf) { + options.revCharsBuf = new Buffer(65536); + var defChar = iconv.defaultCharSingleByte.charCodeAt(0); + for (var i = 0; i < options.revCharsBuf.length; i++) + options.revCharsBuf[i] = defChar; + for (var i = 0; i < options.chars.length; i++) + options.revCharsBuf[options.chars.charCodeAt(i)] = i; + } + + return { + toEncoding: toSingleByteEncoding, + fromEncoding: fromSingleByteEncoding, + options: options, + }; + }, + + // Codepage double-byte encodings. + table: function(options) { + if (!options.table) { + throw new Error("Encoding '" + options.type + "' has incorect 'table' option"); + } + if (!options.revCharsTable) { + var revCharsTable = options.revCharsTable = {}; + for (var i = 0; i <= 0xFFFF; i++) { + revCharsTable[i] = 0; + } + + var table = options.table; + for (var key in table) { + revCharsTable[table[key]] = +key; + } + } + + return { + toEncoding: toTableEncoding, + fromEncoding: fromTableEncoding, + options: options, + }; + } + } +}; + +function toInternalEncoding(str) { + return new Buffer(ensureString(str), this.options.originalEncoding); +} + +function fromInternalEncoding(buf) { + return ensureBuffer(buf).toString(this.options.originalEncoding); +} + +function toTableEncoding(str) { + str = ensureString(str); + var strLen = str.length; + var revCharsTable = this.options.revCharsTable; + var newBuf = new Buffer(strLen*2), gbkcode, unicode, + defaultChar = revCharsTable[iconv.defaultCharUnicode.charCodeAt(0)]; + + for (var i = 0, j = 0; i < strLen; i++) { + unicode = str.charCodeAt(i); + if (unicode >> 7) { + gbkcode = revCharsTable[unicode] || defaultChar; + newBuf[j++] = gbkcode >> 8; //high byte; + newBuf[j++] = gbkcode & 0xFF; //low byte + } else {//ascii + newBuf[j++] = unicode; + } + } + return newBuf.slice(0, j); +} + +function fromTableEncoding(buf) { + buf = ensureBuffer(buf); + var bufLen = buf.length; + var table = this.options.table; + var newBuf = new Buffer(bufLen*2), unicode, gbkcode, + defaultChar = iconv.defaultCharUnicode.charCodeAt(0); + + for (var i = 0, j = 0; i < bufLen; i++, j+=2) { + gbkcode = buf[i]; + if (gbkcode & 0x80) { + gbkcode = (gbkcode << 8) + buf[++i]; + unicode = table[gbkcode] || defaultChar; + } else { + unicode = gbkcode; + } + newBuf[j] = unicode & 0xFF; //low byte + newBuf[j+1] = unicode >> 8; //high byte + } + return newBuf.slice(0, j).toString('ucs2'); +} + +function toSingleByteEncoding(str) { + str = ensureString(str); + + var buf = new Buffer(str.length); + var revCharsBuf = this.options.revCharsBuf; + for (var i = 0; i < str.length; i++) + buf[i] = revCharsBuf[str.charCodeAt(i)]; + + return buf; +} + +function fromSingleByteEncoding(buf) { + buf = ensureBuffer(buf); + + // Strings are immutable in JS -> we use ucs2 buffer to speed up computations. + var charsBuf = this.options.charsBuf; + var newBuf = new Buffer(buf.length*2); + var idx1 = 0, idx2 = 0; + for (var i = 0, _len = buf.length; i < _len; i++) { + idx1 = buf[i]*2; idx2 = i*2; + newBuf[idx2] = charsBuf[idx1]; + newBuf[idx2+1] = charsBuf[idx1+1]; + } + return newBuf.toString('ucs2'); +} + +// Add aliases to convert functions +iconv.encode = iconv.toEncoding; +iconv.decode = iconv.fromEncoding; + +// Load other encodings manually from files in /encodings dir. +function loadEncodings() { + if (!iconv.encodingsLoaded) { + [ require('./encodings/singlebyte'), + require('./encodings/gbk'), + require('./encodings/big5') + ].forEach(function(encodings) { + for (var key in encodings) + iconv.encodings[key] = encodings[key] + }); + iconv.encodingsLoaded = true; + } +} + + + +// Utilities +var asciiString = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'+ + ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f'; + +var ensureBuffer = function(buf) { + buf = buf || new Buffer(0); + return (buf instanceof Buffer) ? buf : new Buffer(""+buf, "binary"); +} + +var ensureString = function(str) { + str = str || ""; + return (str instanceof Buffer) ? str.toString('utf8') : (""+str); +} + +var getType = function(obj) { + return Object.prototype.toString.call(obj).slice(8, -1); +} + diff --git a/node_modules/grunt/node_modules/iconv-lite/package.json b/node_modules/grunt/node_modules/iconv-lite/package.json new file mode 100644 index 000000000..048156071 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/package.json @@ -0,0 +1,84 @@ +{ + "name": "iconv-lite", + "description": "Convert character encodings in pure javascript.", + "version": "0.2.11", + "license": "MIT", + "keywords": [ + "iconv", + "convert", + "charset" + ], + "author": { + "name": "Alexander Shtuchkin", + "email": "ashtuchkin@gmail.com" + }, + "contributors": [ + { + "name": "Jinwu Zhan", + "url": "https://github.com/jenkinv" + }, + { + "name": "Adamansky Anton", + "url": "https://github.com/adamansky" + }, + { + "name": "George Stagas", + "url": "https://github.com/stagas" + }, + { + "name": "Mike D Pilsbury", + "url": "https://github.com/pekim" + }, + { + "name": "Niggler", + "url": "https://github.com/Niggler" + }, + { + "name": "wychi", + "url": "https://github.com/wychi" + }, + { + "name": "David Kuo", + "url": "https://github.com/david50407" + }, + { + "name": "ChangZhuo Chen", + "url": "https://github.com/czchen" + }, + { + "name": "Lee Treveil", + "url": "https://github.com/leetreveil" + }, + { + "name": "Brian White", + "url": "https://github.com/mscdex" + } + ], + "main": "index.js", + "homepage": "https://github.com/ashtuchkin/iconv-lite", + "repository": { + "type": "git", + "url": "git://github.com/ashtuchkin/iconv-lite.git" + }, + "engines": { + "node": ">=0.4.0" + }, + "scripts": { + "test": "vows --spec" + }, + "devDependencies": { + "vows": "", + "iconv": ">=1.1" + }, + "readme": "iconv-lite - pure javascript character encoding conversion\n======================================================================\n\n[![Build Status](https://secure.travis-ci.org/ashtuchkin/iconv-lite.png?branch=master)](http://travis-ci.org/ashtuchkin/iconv-lite)\n\n## Features\n\n* Pure javascript. Doesn't need native code compilation.\n* Easy API.\n* Works on Windows and in sandboxed environments like [Cloud9](http://c9.io).\n* Encoding is much faster than node-iconv (see below for performance comparison).\n\n## Usage\n\n var iconv = require('iconv-lite');\n \n // Convert from an encoded buffer to string.\n str = iconv.decode(buf, 'win1251');\n \n // Convert from string to an encoded buffer.\n buf = iconv.encode(\"Sample input string\", 'win1251');\n\n // Check if encoding is supported\n iconv.encodingExists(\"us-ascii\")\n\n\n## Supported encodings\n\n* All node.js native encodings: 'utf8', 'ucs2', 'ascii', 'binary', 'base64'\n* All widespread single byte encodings: Windows 125x family, ISO-8859 family, \n IBM/DOS codepages, Macintosh family, KOI8 family. \n Aliases like 'latin1', 'us-ascii' also supported.\n* Multibyte encodings: 'gbk', 'gb2313', 'Big5', 'cp950'.\n\nOthers are easy to add, see the source. Please, participate.\nMost encodings are generated from node-iconv. Thank you Ben Noordhuis and iconv authors!\n\nNot supported yet: EUC family, Shift_JIS.\n\n\n## Encoding/decoding speed\n\nComparison with node-iconv module (1000x256kb, on Ubuntu 12.04, Core i5/2.5 GHz, Node v0.8.7). \nNote: your results may vary, so please always check on your hardware.\n\n operation iconv@1.2.4 iconv-lite@0.2.4 \n ----------------------------------------------------------\n encode('win1251') ~115 Mb/s ~230 Mb/s\n decode('win1251') ~95 Mb/s ~130 Mb/s\n\n\n## Notes\n\nWhen decoding, a 'binary'-encoded string can be used as a source buffer. \nUntranslatable characters are set to � or ?. No transliteration is currently supported, pull requests are welcome.\n\n## Testing\n\n git clone git@github.com:ashtuchkin/iconv-lite.git\n cd iconv-lite\n npm install\n npm test\n \n # To view performance:\n node test/performance.js\n\n## TODO\n\n* Support streaming character conversion, something like util.pipe(req, iconv.fromEncodingStream('latin1')).\n* Add more encodings.\n* Add transliteration (best fit char).\n* Add tests and correct support of variable-byte encodings (currently work is delegated to node).\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/ashtuchkin/iconv-lite/issues" + }, + "_id": "iconv-lite@0.2.11", + "dist": { + "shasum": "68f09de81edb0aa31108fd6c65e48f9bfb57a9a9" + }, + "_from": "iconv-lite@~0.2.5", + "_resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" +} diff --git a/node_modules/grunt/node_modules/iconv-lite/test/big5-test.js b/node_modules/grunt/node_modules/iconv-lite/test/big5-test.js new file mode 100644 index 000000000..f3fe1a823 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/big5-test.js @@ -0,0 +1,36 @@ +var vows = require('vows'), + fs = require('fs'), + assert = require('assert'), + iconv = require(__dirname + '/../'); + +var testString = "中文abc", //unicode contains Big5-code and ascii + testStringBig5Buffer = new Buffer([0xa4,0xa4,0xa4,0xe5,0x61,0x62,0x63]), + testString2 = '測試', + testStringBig5Buffer2 = new Buffer([0xb4, 0xfa, 0xb8, 0xd5]); + +vows.describe("Big5 tests").addBatch({ + "Big5 correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testString, "big5").toString('binary'), testStringBig5Buffer.toString('binary')); + assert.strictEqual(iconv.fromEncoding(testStringBig5Buffer, "big5"), testString); + assert.strictEqual(iconv.toEncoding(testString2, 'big5').toString('binary'), testStringBig5Buffer2.toString('binary')); + assert.strictEqual(iconv.fromEncoding(testStringBig5Buffer2, 'big5'), testString2); + }, + "cp950 correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testString, "cp950").toString('binary'), testStringBig5Buffer.toString('binary')); + assert.strictEqual(iconv.fromEncoding(testStringBig5Buffer, "cp950"), testString); + }, + "Big5 file read decoded,compare with iconv result": function() { + var contentBuffer = fs.readFileSync(__dirname+"/big5File.txt"); + var str = iconv.fromEncoding(contentBuffer, "big5"); + var iconvc = new (require('iconv').Iconv)('big5','utf8'); + assert.strictEqual(iconvc.convert(contentBuffer).toString(), str); + }, + "Big5 correctly decodes and encodes characters · and ×": function() { + // https://github.com/ashtuchkin/iconv-lite/issues/13 + // Reference: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT + var chars = "·×"; + var big5Chars = new Buffer([0xA1, 0x50, 0xA1, 0xD1]); + assert.strictEqual(iconv.toEncoding(chars, "big5").toString('binary'), big5Chars.toString('binary')); + assert.strictEqual(iconv.fromEncoding(big5Chars, "big5"), chars) + }, +}).export(module) diff --git a/node_modules/grunt/node_modules/iconv-lite/test/big5File.txt b/node_modules/grunt/node_modules/iconv-lite/test/big5File.txt new file mode 100644 index 000000000..9c13042ca --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/big5File.txt @@ -0,0 +1,13 @@ + + + meta ҪϥΡG + + + + +oO@c餤I
      +(This page uses big5 character set.)
      +charset=big5 + + + \ No newline at end of file diff --git a/node_modules/grunt/node_modules/iconv-lite/test/cyrillic-test.js b/node_modules/grunt/node_modules/iconv-lite/test/cyrillic-test.js new file mode 100644 index 000000000..259d28324 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/cyrillic-test.js @@ -0,0 +1,86 @@ +var vows = require('vows'), + assert = require('assert'), + iconv = require(__dirname+'/../'); + +var baseStrings = { + empty: "", + hi: "Привет!", + ascii: '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'+ + ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f', + rus: "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя", + additional1: "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬\xAD®Ї°±Ііґµ¶·ё№є»јЅѕї", + additional2: "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©", + additional3: " ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏ№ёђѓєѕіїјљњћќ§ўџ", + untranslatable: "£Åçþÿ¿", +}; + +var encodings = [{ + name: "Win-1251", + variations: ['win1251', 'Windows-1251', 'windows1251', 'CP1251', 1251], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\xcf\xf0\xe8\xe2\xe5\xf2!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + rus: new Buffer('\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', 'binary'), + additional1: new Buffer('\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf','binary'), + } +}, { + name: "Koi8-R", + variations: ['koi8r', 'KOI8-R', 'cp20866', 20866], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\xf0\xd2\xc9\xd7\xc5\xd4!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + rus: new Buffer('\xe1\xe2\xf7\xe7\xe4\xe5\xf6\xfa\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf2\xf3\xf4\xf5\xe6\xe8\xe3\xfe\xfb\xfd\xff\xf9\xf8\xfc\xe0\xf1\xc1\xc2\xd7\xc7\xc4\xc5\xd6\xda\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd2\xd3\xd4\xd5\xc6\xc8\xc3\xde\xdb\xdd\xdf\xd9\xd8\xdc\xc0\xd1', 'binary'), + additional2: new Buffer('\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf', 'binary'), + } +}, { + name: "ISO 8859-5", + variations: ['iso88595', 'ISO-8859-5', 'ISO 8859-5', 'cp28595', 28595], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\xbf\xe0\xd8\xd2\xd5\xe2!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + rus: new Buffer('\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef', 'binary'), + additional3: new Buffer('\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', 'binary'), + } +}]; + +var testsBatch = {}; +encodings.forEach(function(encoding) { + var enc = encoding.variations[0]; + var key = "hi"; + var tests = { + "Convert to empty buffer": function() { + assert.strictEqual(iconv.toEncoding("", enc).toString('binary'), new Buffer('').toString('binary')); + }, + "Convert from empty buffer": function() { + assert.strictEqual(iconv.fromEncoding(new Buffer(''), enc), ""); + }, + "Convert from buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), + baseStrings[key]); + }, + "Convert to buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.toEncoding(baseStrings[key], enc).toString('binary'), + encoding.encodedStrings[key].toString('binary')); + }, + "Try different variations of encoding": function() { + encoding.variations.forEach(function(enc) { + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), baseStrings[key]); + assert.strictEqual(iconv.toEncoding(baseStrings[key], enc).toString('binary'), encoding.encodedStrings[key].toString('binary')); + }); + }, + "Untranslatable chars are converted to defaultCharSingleByte": function() { + var expected = baseStrings.untranslatable.split('').map(function(c) {return iconv.defaultCharSingleByte; }).join(''); + assert.strictEqual(iconv.toEncoding(baseStrings.untranslatable, enc).toString('binary'), expected); // Only '?' characters. + } + }; + + testsBatch[encoding.name+":"] = tests; +}); + +vows.describe("Test Cyrillic encodings").addBatch(testsBatch).export(module); + diff --git a/node_modules/grunt/node_modules/iconv-lite/test/gbk-test.js b/node_modules/grunt/node_modules/iconv-lite/test/gbk-test.js new file mode 100644 index 000000000..7b2e47bd4 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/gbk-test.js @@ -0,0 +1,38 @@ +var vows = require('vows'), + fs = require('fs'), + assert = require('assert'), + iconv = require(__dirname+'/../'); + +var testString = "中国abc",//unicode contains GBK-code and ascii + testStringGBKBuffer = new Buffer([0xd6,0xd0,0xb9,0xfa,0x61,0x62,0x63]); + +vows.describe("GBK tests").addBatch({ + "Vows is working": function() {}, + "Return values are of correct types": function() { + assert.ok(iconv.toEncoding(testString, "utf8") instanceof Buffer); + var s = iconv.fromEncoding(new Buffer(testString), "utf8"); + assert.strictEqual(Object.prototype.toString.call(s), "[object String]"); + }, + "GBK correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testString, "GBK").toString('binary'), testStringGBKBuffer.toString('binary')); + assert.strictEqual(iconv.fromEncoding(testStringGBKBuffer, "GBK"), testString); + }, + "GB2312 correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testString, "GB2312").toString('binary'), testStringGBKBuffer.toString('binary')); + assert.strictEqual(iconv.fromEncoding(testStringGBKBuffer, "GB2312"), testString); + }, + "GBK file read decoded,compare with iconv result": function() { + var contentBuffer = fs.readFileSync(__dirname+"/gbkFile.txt"); + var str = iconv.fromEncoding(contentBuffer, "GBK"); + var iconvc = new (require('iconv').Iconv)('GBK','utf8'); + assert.strictEqual(iconvc.convert(contentBuffer).toString(), str); + }, + "GBK correctly decodes and encodes characters · and ×": function() { + // https://github.com/ashtuchkin/iconv-lite/issues/13 + // Reference: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT + var chars = "·×"; + var gbkChars = new Buffer([0xA1, 0xA4, 0xA1, 0xC1]); + assert.strictEqual(iconv.toEncoding(chars, "GBK").toString('binary'), gbkChars.toString('binary')); + assert.strictEqual(iconv.fromEncoding(gbkChars, "GBK"), chars) + }, +}).export(module) diff --git a/node_modules/grunt/node_modules/iconv-lite/test/gbkFile.txt b/node_modules/grunt/node_modules/iconv-lite/test/gbkFile.txt new file mode 100644 index 000000000..345b5d093 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/gbkFile.txt @@ -0,0 +1,14 @@ +ٶһ£֪ + + +
       | ¼
      + + + + + + + + \ No newline at end of file diff --git a/node_modules/grunt/node_modules/iconv-lite/test/greek-test.js b/node_modules/grunt/node_modules/iconv-lite/test/greek-test.js new file mode 100644 index 000000000..0394ee6f5 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/greek-test.js @@ -0,0 +1,79 @@ +var vows = require('vows'), + assert = require('assert'), + iconv = require(__dirname+'/../'); + +var baseStrings = { + empty: "", + hi: "Γειά!", + ascii: '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'+ + ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f', + greek: "αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩάέήίόύώΆΈΉΊΌΎΏϊϋΪΫ", + untranslatable: "Åçþÿ¿" +}; + +var encodings = [{ + name: "windows1253", + variations: ['windows-1253', 'win-1253', 'win1253', 'cp1253', 'cp-1253', 1253], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\xc3\xe5\xe9\xdc!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + greek: new Buffer('\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xdc\xdd\xde\xdf\xfc\xfd\xfe\xa2\xb8\xb9\xba\xbc\xbe\xbf\xfa\xfb\xda\xdb', 'binary'), + } +}, { + name: "iso88597", + variations: ['iso-8859-7', 'greek', 'greek8', 'cp28597', 'cp-28597', 28597], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\xc3\xe5\xe9\xdc!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + greek: new Buffer('\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xdc\xdd\xde\xdf\xfc\xfd\xfe\xb6\xb8\xb9\xba\xbc\xbe\xbf\xfa\xfb\xda\xdb', 'binary'), + } +}, { + name: "cp737", + variations: ['cp-737', 737], + encodedStrings: { + empty: new Buffer(''), + hi: new Buffer('\x82\x9c\xa0\xe1!', 'binary'), + ascii: new Buffer(baseStrings.ascii, 'binary'), + greek: new Buffer('\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xab\xac\xad\xae\xaf\xe0\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\xe1\xe2\xe3\xe5\xe6\xe7\xe9\xea\xeb\xec\xed\xee\xef\xf0\xe4\xe8\xf4\xf5', 'binary'), + } +}]; + +var testsBatch = {}; +encodings.forEach(function(encoding) { + var enc = encoding.variations[0]; + var key = "hi"; + var tests = { + "Convert to empty buffer": function() { + assert.strictEqual(iconv.toEncoding("", enc).toString('binary'), new Buffer('').toString('binary')); + }, + "Convert from empty buffer": function() { + assert.strictEqual(iconv.fromEncoding(new Buffer(''), enc), ""); + }, + "Convert from buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), + baseStrings[key]); + }, + "Convert to buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.toEncoding(baseStrings[key], enc).toString('binary'), + encoding.encodedStrings[key].toString('binary')); + }, + "Try different variations of encoding": function() { + encoding.variations.forEach(function(enc) { + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), baseStrings[key]); + assert.strictEqual(iconv.toEncoding(baseStrings[key], enc).toString('binary'), encoding.encodedStrings[key].toString('binary')); + }); + }, + "Untranslatable chars are converted to defaultCharSingleByte": function() { + var expected = baseStrings.untranslatable.split('').map(function(c) {return iconv.defaultCharSingleByte; }).join(''); + assert.strictEqual(iconv.toEncoding(baseStrings.untranslatable, enc).toString('binary'), expected); // Only '?' characters. + } + }; + + testsBatch[encoding.name+":"] = tests; +}); + +vows.describe("Test Greek encodings").addBatch(testsBatch).export(module); diff --git a/node_modules/grunt/node_modules/iconv-lite/test/main-test.js b/node_modules/grunt/node_modules/iconv-lite/test/main-test.js new file mode 100644 index 000000000..50177f221 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/main-test.js @@ -0,0 +1,55 @@ +var vows = require('vows'), + assert = require('assert'), + iconv = require(__dirname+'/../'); + +var testString = "Hello123!"; +var testStringLatin1 = "Hello123!£Å÷×çþÿ¿®"; +var testStringBase64 = "SGVsbG8xMjMh"; + +vows.describe("Generic UTF8-UCS2 tests").addBatch({ + "Vows is working": function() {}, + "Return values are of correct types": function() { + assert.ok(iconv.toEncoding(testString, "utf8") instanceof Buffer); + + var s = iconv.fromEncoding(new Buffer(testString), "utf8"); + assert.strictEqual(Object.prototype.toString.call(s), "[object String]"); + }, + "Internal encodings all correctly encoded/decoded": function() { + ['utf8', "UTF-8", "UCS2", "binary", ""].forEach(function(enc) { + assert.strictEqual(iconv.toEncoding(testStringLatin1, enc).toString(enc), testStringLatin1); + assert.strictEqual(iconv.fromEncoding(new Buffer(testStringLatin1, enc), enc), testStringLatin1); + }); + }, + "Base64 correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testStringBase64, "base64").toString("binary"), testString); + assert.strictEqual(iconv.fromEncoding(new Buffer(testString, "binary"), "base64"), testStringBase64); + }, + "Latin1 correctly encoded/decoded": function() { + assert.strictEqual(iconv.toEncoding(testStringLatin1, "latin1").toString("binary"), testStringLatin1); + assert.strictEqual(iconv.fromEncoding(new Buffer(testStringLatin1, "binary"), "latin1"), testStringLatin1); + }, + "Convert from string, not buffer (binary encoding used)": function() { + assert.strictEqual(iconv.fromEncoding(testStringLatin1, "binary"), testStringLatin1); + }, + "Convert to string, not buffer (utf8 used)": function() { + var res = iconv.toEncoding(new Buffer(testStringLatin1, "utf8")); + assert.ok(res instanceof Buffer); + assert.strictEqual(res.toString("utf8"), testStringLatin1); + }, + "Throws on unknown encodings": function() { + assert.throws(function() { iconv.toEncoding("a", "xxx"); }); + assert.throws(function() { iconv.fromEncoding("a", "xxx"); }); + }, + "Convert non-strings and non-buffers": function() { + assert.strictEqual(iconv.toEncoding({}, "utf8").toString(), "[object Object]"); + assert.strictEqual(iconv.toEncoding(10, "utf8").toString(), "10"); + assert.strictEqual(iconv.toEncoding(undefined, "utf8").toString(), ""); + assert.strictEqual(iconv.fromEncoding({}, "utf8"), "[object Object]"); + assert.strictEqual(iconv.fromEncoding(10, "utf8"), "10"); + assert.strictEqual(iconv.fromEncoding(undefined, "utf8"), ""); + }, + "Aliases encode and decode work the same as toEncoding and fromEncoding": function() { + assert.strictEqual(iconv.toEncoding(testString, "latin1").toString("binary"), iconv.encode(testString, "latin1").toString("binary")); + assert.strictEqual(iconv.fromEncoding(testStringLatin1, "latin1"), iconv.decode(testStringLatin1, "latin1")); + }, +}).export(module) diff --git a/node_modules/grunt/node_modules/iconv-lite/test/performance.js b/node_modules/grunt/node_modules/iconv-lite/test/performance.js new file mode 100644 index 000000000..835deac57 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/performance.js @@ -0,0 +1,67 @@ + +var iconv = require('iconv'); +var iconv_lite = require("../index"); + +var encoding = process.argv[2] || "windows-1251"; +var convertTimes = 10000; + +var encodingStrings = { + 'windows-1251': 'This is a test string 32 chars..', + 'gbk': '这是中文字符测试。。!@¥%12', + 'utf8': '这是中文字符测试。。!@¥%12This is a test string 48 chars..', +}; +// Test encoding. +var str = encodingStrings[encoding]; +if (!str) { + throw new Error('Don\'t support ' + encoding + ' performance test.'); +} +for (var i = 0; i < 13; i++) { + str = str + str; +} + +console.log('\n' + encoding + ' charset performance test:'); +console.log("\nEncoding "+str.length+" chars "+convertTimes+" times:"); + +var start = Date.now(); +var converter = new iconv.Iconv("utf8", encoding); +for (var i = 0; i < convertTimes; i++) { + var b = converter.convert(str); +} +var duration = Date.now() - start; +var mbs = convertTimes*b.length/duration/1024; + +console.log("iconv: "+duration+"ms, "+mbs.toFixed(2)+" Mb/s."); + +var start = Date.now(); +for (var i = 0; i < convertTimes; i++) { + var b = iconv_lite.encode(str, encoding); +} +var duration = Date.now() - start; +var mbs = convertTimes*b.length/duration/1024; + +console.log("iconv-lite: "+duration+"ms, "+mbs.toFixed(2)+" Mb/s."); + + +// Test decoding. +var buf = iconv_lite.encode(str, encoding); +console.log("\nDecoding "+buf.length+" bytes "+convertTimes+" times:"); + +var start = Date.now(); +var converter = new iconv.Iconv(encoding, "utf8"); +for (var i = 0; i < convertTimes; i++) { + var s = converter.convert(buf).toString(); +} +var duration = Date.now() - start; +var mbs = convertTimes*buf.length/duration/1024; + +console.log("iconv: "+duration+"ms, "+mbs.toFixed(2)+" Mb/s."); + +var start = Date.now(); +for (var i = 0; i < convertTimes; i++) { + var s = iconv_lite.decode(buf, encoding); +} +var duration = Date.now() - start; +var mbs = convertTimes*buf.length/duration/1024; + +console.log("iconv-lite: "+duration+"ms, "+mbs.toFixed(2)+" Mb/s."); + diff --git a/node_modules/grunt/node_modules/iconv-lite/test/turkish-test.js b/node_modules/grunt/node_modules/iconv-lite/test/turkish-test.js new file mode 100644 index 000000000..b2eb68e67 --- /dev/null +++ b/node_modules/grunt/node_modules/iconv-lite/test/turkish-test.js @@ -0,0 +1,90 @@ +var vows = require('vows'), + assert = require('assert'), + iconv = require(__dirname+'/../'); + +var ascii = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'+ + ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f'; + +var encodings = [{ + name: "windows1254", + variations: ['windows-1254', 'win-1254', 'win1254', 'cp1254', 'cp-1254', 1254], + strings: { + empty: "", + ascii: ascii, + turkish: "€‚ƒ„…†‡ˆ‰Š‹Œ‘’“”•–—˜™š›œŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ", + untranslatable: "\x81\x8d\x8e\x8f\x90\x9d\x9e" + }, + encodedStrings: { + empty: new Buffer(''), + ascii: new Buffer(ascii, 'binary'), + turkish: new Buffer( + '\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c' + + '\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9f' + + '\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xae\xaf' + + '\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf' + + '\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf' + + '\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf' + + '\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef' + + '\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', + 'binary'), + } +}, { + name: "iso88599", + variations: ['iso-8859-9', 'turkish', 'turkish8', 'cp28599', 'cp-28599', 28599], + strings: { + empty: "", + ascii: ascii, + turkish: "\xa0¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ", + untranslatable: '' + }, + encodedStrings: { + empty: new Buffer(''), + ascii: new Buffer(ascii, 'binary'), + turkish: new Buffer( + '\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf' + + '\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf' + + '\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf' + + '\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf' + + '\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef' + + '\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff', + 'binary') + } +}]; + +var testsBatch = {}; +encodings.forEach(function(encoding) { + var enc = encoding.variations[0]; + var key = "turkish"; + var tests = { + "Convert to empty buffer": function() { + assert.strictEqual(iconv.toEncoding("", enc).toString('binary'), new Buffer('').toString('binary')); + }, + "Convert from empty buffer": function() { + assert.strictEqual(iconv.fromEncoding(new Buffer(''), enc), ""); + }, + "Convert from buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), + encoding.strings[key]); + }, + "Convert to buffer": function() { + for (var key in encoding.encodedStrings) + assert.strictEqual(iconv.toEncoding(encoding.strings[key], enc).toString('binary'), + encoding.encodedStrings[key].toString('binary')); + }, + "Try different variations of encoding": function() { + encoding.variations.forEach(function(enc) { + assert.strictEqual(iconv.fromEncoding(encoding.encodedStrings[key], enc), encoding.strings[key]); + assert.strictEqual(iconv.toEncoding(encoding.strings[key], enc).toString('binary'), encoding.encodedStrings[key].toString('binary')); + }); + }, + "Untranslatable chars are converted to defaultCharSingleByte": function() { + var expected = encoding.strings.untranslatable.split('').map(function(c) {return iconv.defaultCharSingleByte; }).join(''); + assert.strictEqual(iconv.toEncoding(encoding.strings.untranslatable, enc).toString('binary'), expected); // Only '?' characters. + } + }; + + testsBatch[encoding.name+":"] = tests; +}); + +vows.describe("Test Turkish encodings").addBatch(testsBatch).export(module); diff --git a/node_modules/grunt/node_modules/js-yaml/HISTORY.md b/node_modules/grunt/node_modules/js-yaml/HISTORY.md new file mode 100644 index 000000000..dfc48c2b1 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/HISTORY.md @@ -0,0 +1,155 @@ +2.0.5 / 2013-04-26 +------------------ + +* Close security issue in !!js/function constructor. + Big thanks to @nealpoole for security audit. + + +2.0.4 / 2013-04-08 +------------------ + +* Updated .npmignore to reduce package size + + +2.0.3 / 2013-02-26 +------------------ + +* Fixed dumping of empty arrays ans objects. ([] and {} instead of null) + + +2.0.2 / 2013-02-15 +------------------ + +* Fixed input validation: tabs are printable characters. + + +2.0.1 / 2013-02-09 +------------------ + +* Fixed error, when options not passed to function cass + + +2.0.0 / 2013-02-09 +------------------ + +* Full rewrite. New architecture. Fast one-stage parsing. +* Changed custom types API. +* Added YAML dumper. + + +1.0.3 / 2012-11-05 +------------------ + +* Fixed utf-8 files loading. + + +1.0.2 / 2012-08-02 +------------------ + +* Pull out hand-written shims. Use ES5-Shims for old browsers support. See #44. +* Fix timstamps incorectly parsed in local time when no time part specified. + + +1.0.1 / 2012-07-07 +------------------ + +* Fixes `TypeError: 'undefined' is not an object` under Safari. Thanks Phuong. +* Fix timestamps incorrectly parsed in local time. Thanks @caolan. Closes #46. + + +1.0.0 / 2012-07-01 +------------------ + +* `y`, `yes`, `n`, `no`, `on`, `off` are not converted to Booleans anymore. + Fixes #42. +* `require(filename)` now returns a single document and throws an Error if + file contains more than one document. +* CLI was merged back from js-yaml.bin + + +0.3.7 / 2012-02-28 +------------------ + +* Fix export of `addConstructor()`. Closes #39. + + +0.3.6 / 2012-02-22 +------------------ + +* Removed AMD parts - too buggy to use. Need help to rewrite from scratch +* Removed YUI compressor warning (renamed `double` variable). Closes #40. + + +0.3.5 / 2012-01-10 +------------------ + +* Workagound for .npmignore fuckup under windows. Thanks to airportyh. + + +0.3.4 / 2011-12-24 +------------------ + +* Fixes str[] for oldIEs support. +* Adds better has change support for browserified demo. +* improves compact output of Error. Closes #33. + + +0.3.3 / 2011-12-20 +------------------ + +* jsyaml executable moved to separate module. +* adds `compact` stringification of Errors. + + +0.3.2 / 2011-12-16 +------------------ + +* Fixes ug with block style scalars. Closes #26. +* All sources are passing JSLint now. +* Fixes bug in Safari. Closes #28. +* Fixes bug in Opers. Closes #29. +* Improves browser support. Closes #20. +* Added jsyaml executable. +* Added !!js/function support. Closes #12. + + +0.3.1 / 2011-11-18 +------------------ + +* Added AMD support for browserified version. +* Wrapped browserified js-yaml into closure. +* Fixed the resolvement of non-specific tags. Closes #17. +* Added permalinks for online demo YAML snippets. Now we have YPaste service, lol. +* Added !!js/regexp and !!js/undefined types. Partially solves #12. +* Fixed !!set mapping. +* Fixed month parse in dates. Closes #19. + + +0.3.0 / 2011-11-09 +------------------ + +* Removed JS.Class dependency. Closes #3. +* Added browserified version. Closes #13. +* Added live demo of browserified version. +* Ported some of the PyYAML tests. See #14. +* Fixed timestamp bug when fraction was given. + + +0.2.2 / 2011-11-06 +------------------ + +* Fixed crash on docs without ---. Closes #8. +* Fixed miltiline string parse +* Fixed tests/comments for using array as key + + +0.2.1 / 2011-11-02 +------------------ + +* Fixed short file read (<4k). Closes #9. + + +0.2.0 / 2011-11-02 +------------------ + +* First public release diff --git a/node_modules/grunt/node_modules/js-yaml/LICENSE b/node_modules/grunt/node_modules/js-yaml/LICENSE new file mode 100644 index 000000000..0f16ee957 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/LICENSE @@ -0,0 +1,21 @@ +(The MIT License) + +Copyright (C) 2011, 2013 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/js-yaml/README.md b/node_modules/grunt/node_modules/js-yaml/README.md new file mode 100644 index 000000000..e326d6026 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/README.md @@ -0,0 +1,249 @@ +JS-YAML - YAML 1.2 parser and serializer for JavaScript +======================================================= + +[![Build Status](https://secure.travis-ci.org/nodeca/js-yaml.png)](http://travis-ci.org/nodeca/js-yaml) + +[Online Demo](http://nodeca.github.com/js-yaml/) + + +This is an implementation of [YAML](http://yaml.org/), a human friendly data +serialization language. Started as [PyYAML](http://pyyaml.org/) port, it was +completely rewritten from scratch. Now it's very fast, and supports 1.2 spec. + + +Breaking changes in 1.x.x -> 2.0.x +---------------------------------- + +If your have not used __custom__ tags or loader classes - no changes needed. Just +upgrade library and enjoy high parse speed. + +In other case, you should rewrite your tag constructors and custom loader +classes, to conform new schema-based API. See +[examples](https://github.com/nodeca/js-yaml/tree/master/examples) and +[wiki](https://github.com/nodeca/js-yaml/wiki) for details. +Note, that parser internals were completely rewritten. + + +Installation +------------ + +### YAML module for node.js + +``` +npm install js-yaml +``` + + +### CLI executable + +If you want to inspect your YAML files from CLI, install js-yaml globally: + +``` +npm install js-yaml -g +``` + +#### Usage + +``` +usage: js-yaml [-h] [-v] [-c] [-j] [-t] file + +Positional arguments: + file File with YAML document(s) + +Optional arguments: + -h, --help Show this help message and exit. + -v, --version Show program's version number and exit. + -c, --compact Display errors in compact mode + -j, --to-json Output a non-funky boring JSON + -t, --trace Show stack trace on error +``` + + +### Bundled YAML library for browsers + +``` html + + +``` + +Browser support was done mostly for online demo. If you find any errors - feel +free to send pull requests with fixes. Also note, that IE and other old browsers +needs [es5-shims](https://github.com/kriskowal/es5-shim) to operate. + + +API +--- + +Here we cover the most 'useful' methods. If you need advanced details (creating +your own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and +[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more +info. + +In node.js JS-YAML automatically registers handlers for `.yml` and `.yaml` +files. You can load them just with `require`. That's mostly equivalent to +calling `load()` on fetched content of a file. Just with one string! + +``` javascript +require('js-yaml'); + +// Get document, or throw exception on error +try { + var doc = require('/home/ixti/example.yml'); + console.log(doc); +} catch (e) { + console.log(e); +} +``` + + +### load (string [ , options ]) + +Parses `string` as single YAML document. Returns a JavaScript object or throws +`YAMLException` on error. + +NOTE: This function **does not** understands multi-document sources, it throws +exception on those. + +options: + +- `filename` _(default: null)_ - string to be used as a file path in + error/warning messages. +- `strict` _(default - false)_ makes the loader to throw errors instead of + warnings. +- `schema` _(default: `DEFAULT_SCHEMA`)_ - specifies a schema to use. + + +### loadAll (string, iterator [ , options ]) + +Same as `load()`, but understands multi-document sources and apply `iterator` to +each document. + +``` javascript +var yaml = require('js-yaml'); + +yaml.loadAll(data, function (doc) { + console.log(doc); +}); +``` + + +### safeLoad (string [ , options ]) + +Same as `load()` but uses `SAFE_SCHEMA` by default - only recommended tags of +YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). + + +### safeLoadAll (string, iterator [ , options ]) + +Same as `loadAll()` but uses `SAFE_SCHEMA` by default - only recommended tags of +YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). + + +### dump (object [ , options ]) + +Serializes `object` as YAML document. + +options: + +- `indent` _(default: 2)_ - indentation width to use (in spaces). +- `flowLevel` (default: -1) - specifies level of nesting, when to switch from + block to flow style for collections. -1 means block style everwhere +- `styles` - "tag" => "style" map. Each tag may have own set of styles. +- `schema` _(default: `DEFAULT_SCHEMA`)_ specifies a schema to use. + +styles: + +``` none +!!null + "canonical" => "~" + +!!int + "binary" => "0b1", "0b101010", "0b1110001111010" + "octal" => "01", "052", "016172" + "decimal" => "1", "42", "7290" + "hexadecimal" => "0x1", "0x2A", "0x1C7A" + +!!null, !!bool, !!float + "lowercase" => "null", "true", "false", ".nan", '.inf' + "uppercase" => "NULL", "TRUE", "FALSE", ".NAN", '.INF' + "camelcase" => "Null", "True", "False", ".NaN", '.Inf' +``` + +By default, !!int uses `decimal`, and !!null, !!bool, !!float use `lowercase`. + + +### safeDump (object [ , options ]) + +Same as `dump()` but uses `SAFE_SCHEMA` by default - only recommended tags of +YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). + + +Supported YAML types +-------------------- + +The list of standard YAML tags and corresponding JavaScipt types. See also +[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and +[YAML types repository](http://yaml.org/type/). + +``` +!!null '' # null +!!bool 'yes' # bool +!!int '3...' # number +!!float '3.14...' # number +!!binary '...base64...' # buffer +!!timestamp 'YYYY-...' # date +!!omap [ ... ] # array of key-value pairs +!!pairs [ ... ] # array or array pairs +!!set { ... } # array of objects with given keys and null values +!!str '...' # string +!!seq [ ... ] # array +!!map { ... } # object +``` + +**JavaScript-specific tags** + +``` +!!js/regexp /pattern/gim # RegExp +!!js/undefined '' # Undefined +!!js/function 'function () {...}' # Function +``` + + + + +## Caveats + +Note, that you use arrays or objects as key in JS-YAML. JS do not allows objects +or array as keys, and stringifies (by calling .toString method) them at the +moment of adding them. + +``` yaml +--- +? [ foo, bar ] +: - baz +? { foo: bar } +: - baz + - baz +``` + +``` javascript +{ "foo,bar": ["baz"], "[object Object]": ["baz", "baz"] } +``` + +Also, reading of properties on implicit block mapping keys is not supported yet. +So, the following YAML document cannot be loaded. + +``` yaml +&anchor foo: + foo: bar + *anchor: duplicate key + baz: bat + *anchor: duplicate key +``` + +## License + +View the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file +(MIT). diff --git a/node_modules/grunt/node_modules/js-yaml/bin/js-yaml.js b/node_modules/grunt/node_modules/js-yaml/bin/js-yaml.js new file mode 100755 index 000000000..5110a4c7a --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/bin/js-yaml.js @@ -0,0 +1,125 @@ +#!/usr/bin/env node + + +'use strict'; + + +// stdlib +var fs = require('fs'); +var util = require('util'); + + +// 3rd-party +var ArgumentParser = require('argparse').ArgumentParser; + + +// internal +var yaml = require('..'); + + +//////////////////////////////////////////////////////////////////////////////// + + +var cli = new ArgumentParser({ + prog: 'js-yaml', + version: require('../package.json').version, + addHelp: true +}); + + +cli.addArgument(['-c', '--compact'], { + help: 'Display errors in compact mode', + action: 'storeTrue' +}); + + +cli.addArgument(['-j', '--to-json'], { + help: 'Output a non-funky boring JSON', + dest: 'json', + action: 'storeTrue' +}); + + +cli.addArgument(['-t', '--trace'], { + help: 'Show stack trace on error', + action: 'storeTrue' +}); + + +cli.addArgument(['file'], { + help: 'File to read' +}); + + +//////////////////////////////////////////////////////////////////////////////// + + +var options = cli.parseArgs(); + + +//////////////////////////////////////////////////////////////////////////////// + + +fs.readFile(options.file, 'utf8', function (error, input) { + var output, isYaml; + + if (error) { + if ('ENOENT' === error.code) { + console.error('File not found: ' + options.file); + process.exit(2); + } + + console.error( + options.trace && error.stack || + error.message || + String(error)); + + process.exit(1); + } + + try { + output = JSON.parse(input); + isYaml = false; + } catch (error) { + if (error instanceof SyntaxError) { + try { + output = []; + yaml.loadAll(input, function (doc) { output.push(doc); }, {}); + isYaml = true; + + if (0 === output.length) { + output = null; + } else if (1 === output.length) { + output = output[0]; + } + } catch (error) { + if (options.trace && error.stack) { + console.error(error.stack); + } else { + console.error(error.toString(options.compact)); + } + + process.exit(1); + } + } else { + console.error( + options.trace && error.stack || + error.message || + String(error)); + + process.exit(1); + } + } + + if (isYaml) { + if (options.json) { + console.log(JSON.stringify(output, null, ' ')); + } else { + console.log("\n" + util.inspect(output, false, 10, true) + "\n"); + } + } else { + console.log(yaml.dump(output)); + } + + process.exit(0); +}); diff --git a/node_modules/grunt/node_modules/js-yaml/examples/custom_types.js b/node_modules/grunt/node_modules/js-yaml/examples/custom_types.js new file mode 100644 index 000000000..1cb987c16 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/custom_types.js @@ -0,0 +1,104 @@ +'use strict'; + + +var fs = require('fs'); +var path = require('path'); +var util = require('util'); +var yaml = require('../lib/js-yaml'); + + +// Let define a couple of classes... + +function Point(x, y, z) { + this.klass = 'Point'; + this.x = x; + this.y = y; + this.z = z; +} + + +function Space(height, width, points) { + if (points) { + if (!points.every(function (point) { return point instanceof Point; })) { + throw new Error('A non-Point inside a points array!'); + } + } + + this.klass = 'Space'; + this.height = height; + this.width = width; + this.points = points; +} + + +// Let define YAML types to load and dump our Point/Space objects. + +var pointYamlType = new yaml.Type('!point', { + // The information used to load a Point. + loader: { + kind: 'array', // It must be an array. (sequence in YAML) + resolver: function (object) { + // It must contain exactly tree elements. + if (3 === object.length) { + return new Point(object[0], object[1], object[2]); + + // Otherwise, it is NOT a Point. + } else { + return yaml.NIL; + } + } + }, + // The information used to dump a Point. + dumper: { + kind: 'object', // It must be an object but not an array. + instanceOf: Point, // Also, it must be an instance of Point class. + representer: function (point) { + // And it should be represented in YAML as three-element sequence. + return [ point.x, point.y, point.z ]; + } + } +}); + + +var spaceYamlType = new yaml.Type('!space', { + loader: { + kind: 'object', // 'object' here means 'mapping' in YAML. + resolver: function (object) { + return new Space(object.height, object.width, object.points); + } + }, + dumper: { + kind: 'object', + instanceOf: Space + // The representer is omitted here. So, Space objects will be dumped as is. + // That is regular mapping with three key-value pairs but with !space tag. + } +}); + + +// After our types are defined, it's time to join them into a schema. + +var SPACE_SCHEMA = yaml.Schema.create([ spaceYamlType, pointYamlType ]); + + +// And read a document using that schema. + +fs.readFile(path.join(__dirname, 'custom_types.yaml'), 'utf8', function (error, data) { + var loaded; + + if (!error) { + loaded = yaml.load(data, { schema: SPACE_SCHEMA }); + console.log(util.inspect(loaded, false, 20, true)); + } else { + console.error(error.stack || error.message || String(error)); + } +}); + + +// There are some exports to play with this example interactively. + +module.exports.Point = Point; +module.exports.Space = Space; +module.exports.pointYamlType = pointYamlType; +module.exports.spaceYamlType = spaceYamlType; +module.exports.SPACE_SCHEMA = SPACE_SCHEMA; diff --git a/node_modules/grunt/node_modules/js-yaml/examples/custom_types.yaml b/node_modules/grunt/node_modules/js-yaml/examples/custom_types.yaml new file mode 100644 index 000000000..033134f5e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/custom_types.yaml @@ -0,0 +1,18 @@ +subject: Custom types in JS-YAML +spaces: +- !space + height: 1000 + width: 1000 + points: + - !point [ 10, 43, 23 ] + - !point [ 165, 0, 50 ] + - !point [ 100, 100, 100 ] + +- !space + height: 64 + width: 128 + points: + - !point [ 12, 43, 0 ] + - !point [ 1, 4, 90 ] + +- !space {} # An empty space diff --git a/node_modules/grunt/node_modules/js-yaml/examples/dumper.js b/node_modules/grunt/node_modules/js-yaml/examples/dumper.js new file mode 100644 index 000000000..7952b18d2 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/dumper.js @@ -0,0 +1,31 @@ +'use strict'; + + +var yaml = require('../lib/js-yaml'); +var object = require('./dumper.json'); + + +console.log(yaml.dump(object, { + flowLevel: 3, + styles: { + '!!int' : 'hexadecimal', + '!!null' : 'camelcase' + } +})); + + +// Output: +//============================================================================== +// name: Wizzard +// level: 0x11 +// sanity: Null +// inventory: +// - name: Hat +// features: [magic, pointed] +// traits: {} +// - name: Staff +// features: [] +// traits: {damage: 0xA} +// - name: Cloak +// features: [old] +// traits: {defence: 0x0, comfort: 0x3} diff --git a/node_modules/grunt/node_modules/js-yaml/examples/dumper.json b/node_modules/grunt/node_modules/js-yaml/examples/dumper.json new file mode 100644 index 000000000..9f54c053e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/dumper.json @@ -0,0 +1,22 @@ +{ + "name" : "Wizzard", + "level" : 17, + "sanity" : null, + "inventory" : [ + { + "name" : "Hat", + "features" : [ "magic", "pointed" ], + "traits" : {} + }, + { + "name" : "Staff", + "features" : [], + "traits" : { "damage" : 10 } + }, + { + "name" : "Cloak", + "features" : [ "old" ], + "traits" : { "defence" : 0, "comfort" : 3 } + } + ] +} diff --git a/node_modules/grunt/node_modules/js-yaml/examples/sample_document.js b/node_modules/grunt/node_modules/js-yaml/examples/sample_document.js new file mode 100644 index 000000000..1ce370d89 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/sample_document.js @@ -0,0 +1,15 @@ +'use strict'; + + +var inspect = require('util').inspect; + +// just require jsyaml +require('../lib/js-yaml'); + + +try { + var doc = require(__dirname + '/sample_document.yaml'); + console.log(inspect(doc, false, 10, true)); +} catch (e) { + console.log(e.stack || e.toString()); +} diff --git a/node_modules/grunt/node_modules/js-yaml/examples/sample_document.yaml b/node_modules/grunt/node_modules/js-yaml/examples/sample_document.yaml new file mode 100644 index 000000000..4479ee9c0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/examples/sample_document.yaml @@ -0,0 +1,197 @@ +--- +# Collection Types ############################################################# +################################################################################ + +# http://yaml.org/type/map.html -----------------------------------------------# + +map: + # Unordered set of key: value pairs. + Block style: !!map + Clark : Evans + Ingy : döt Net + Oren : Ben-Kiki + Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki } + +# http://yaml.org/type/omap.html ----------------------------------------------# + +omap: + # Explicitly typed ordered map (dictionary). + Bestiary: !!omap + - aardvark: African pig-like ant eater. Ugly. + - anteater: South-American ant eater. Two species. + - anaconda: South-American constrictor snake. Scaly. + # Etc. + # Flow style + Numbers: !!omap [ one: 1, two: 2, three : 3 ] + +# http://yaml.org/type/pairs.html ---------------------------------------------# + +pairs: + # Explicitly typed pairs. + Block tasks: !!pairs + - meeting: with team. + - meeting: with boss. + - break: lunch. + - meeting: with client. + Flow tasks: !!pairs [ meeting: with team, meeting: with boss ] + +# http://yaml.org/type/set.html -----------------------------------------------# + +set: + # Explicitly typed set. + baseball players: !!set + ? Mark McGwire + ? Sammy Sosa + ? Ken Griffey + # Flow style + baseball teams: !!set { Boston Red Sox, Detroit Tigers, New York Yankees } + +# http://yaml.org/type/seq.html -----------------------------------------------# + +seq: + # Ordered sequence of nodes + Block style: !!seq + - Mercury # Rotates - no light/dark sides. + - Venus # Deadliest. Aptly named. + - Earth # Mostly dirt. + - Mars # Seems empty. + - Jupiter # The king. + - Saturn # Pretty. + - Uranus # Where the sun hardly shines. + - Neptune # Boring. No rings. + - Pluto # You call this a planet? + Flow style: !!seq [ Mercury, Venus, Earth, Mars, # Rocks + Jupiter, Saturn, Uranus, Neptune, # Gas + Pluto ] # Overrated + + +# Scalar Types ################################################################# +################################################################################ + +# http://yaml.org/type/binary.html --------------------------------------------# + +binary: + canonical: !!binary "\ + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\ + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\ + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=" + generic: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + description: + The binary value above is a tiny arrow encoded as a gif image. + +# http://yaml.org/type/bool.html ----------------------------------------------# + +bool: + - true + - True + - TRUE + - false + - False + - FALSE + +# http://yaml.org/type/float.html ---------------------------------------------# + +float: + canonical: 6.8523015e+5 + exponentioal: 685.230_15e+03 + fixed: 685_230.15 + sexagesimal: 190:20:30.15 + negative infinity: -.inf + not a number: .NaN + +# http://yaml.org/type/int.html -----------------------------------------------# + +int: + canonical: 685230 + decimal: +685_230 + octal: 02472256 + hexadecimal: 0x_0A_74_AE + binary: 0b1010_0111_0100_1010_1110 + sexagesimal: 190:20:30 + +# http://yaml.org/type/merge.html ---------------------------------------------# + +merge: + - &CENTER { x: 1, y: 2 } + - &LEFT { x: 0, y: 2 } + - &BIG { r: 10 } + - &SMALL { r: 1 } + + # All the following maps are equal: + + - # Explicit keys + x: 1 + y: 2 + r: 10 + label: nothing + + - # Merge one map + << : *CENTER + r: 10 + label: center + + - # Merge multiple maps + << : [ *CENTER, *BIG ] + label: center/big + + - # Override + << : [ *BIG, *LEFT, *SMALL ] + x: 1 + label: big/left/small + +# http://yaml.org/type/null.html ----------------------------------------------# + +null: + # This mapping has four keys, + # one has a value. + empty: + canonical: ~ + english: null + ~: null key + # This sequence has five + # entries, two have values. + sparse: + - ~ + - 2nd entry + - + - 4th entry + - Null + +# http://yaml.org/type/str.html -----------------------------------------------# + +string: abcd + +# http://yaml.org/type/timestamp.html -----------------------------------------# + +timestamp: + canonical: 2001-12-15T02:59:43.1Z + valid iso8601: 2001-12-14t21:59:43.10-05:00 + space separated: 2001-12-14 21:59:43.10 -5 + no time zone (Z): 2001-12-15 2:59:43.10 + date (00:00:00Z): 2002-12-14 + + +# JavaScript Specific Types #################################################### +################################################################################ + +# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp + +regexp: + simple: !!js/regexp foobar + modifiers: !!js/regexp /foobar/mi + +# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined + +undefined: !!js/undefined ~ + +# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function + +function: !!js/function > + function foobar() { + return 'Wow! JS-YAML Rocks!'; + } diff --git a/node_modules/grunt/node_modules/js-yaml/index.js b/node_modules/grunt/node_modules/js-yaml/index.js new file mode 100644 index 000000000..40606ddc2 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/js-yaml.js'); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml.js new file mode 100644 index 000000000..a5146a326 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml.js @@ -0,0 +1,33 @@ +'use strict'; + + +var loader = require('./js-yaml/loader'); +var dumper = require('./js-yaml/dumper'); + + +function deprecated(name) { + return function () { + throw new Error('Function ' + name + ' is deprecated and cannot be used.'); + }; +} + + +module.exports.Type = require('./js-yaml/type'); +module.exports.Schema = require('./js-yaml/schema'); +module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/minimal'); +module.exports.SAFE_SCHEMA = require('./js-yaml/schema/safe'); +module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default'); +module.exports.load = loader.load; +module.exports.loadAll = loader.loadAll; +module.exports.safeLoad = loader.safeLoad; +module.exports.safeLoadAll = loader.safeLoadAll; +module.exports.dump = dumper.dump; +module.exports.safeDump = dumper.safeDump; +module.exports.YAMLException = require('./js-yaml/exception'); +module.exports.scan = deprecated('scan'); +module.exports.parse = deprecated('parse'); +module.exports.compose = deprecated('compose'); +module.exports.addConstructor = deprecated('addConstructor'); + + +require('./js-yaml/require'); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/common.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/common.js new file mode 100644 index 000000000..cc7f824cc --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/common.js @@ -0,0 +1,60 @@ +'use strict'; + + +var NIL = {}; + + +function isNothing(subject) { + return (undefined === subject) || (null === subject); +} + + +function isObject(subject) { + return ('object' === typeof subject) && (null !== subject); +} + + +function toArray(sequence) { + if (Array.isArray(sequence)) { + return sequence; + } else if (isNothing(sequence)) { + return []; + } else { + return [ sequence ]; + } +} + + +function extend(target, source) { + var index, length, key, sourceKeys; + + if (source) { + sourceKeys = Object.keys(source); + + for (index = 0, length = sourceKeys.length; index < length; index += 1) { + key = sourceKeys[index]; + target[key] = source[key]; + } + } + + return target; +} + + +function repeat(string, count) { + var result = '', cycle; + + for (cycle = 0; cycle < count; cycle += 1) { + result += string; + } + + return result; +} + + +module.exports.NIL = NIL; +module.exports.isNothing = isNothing; +module.exports.isObject = isObject; +module.exports.toArray = toArray; +module.exports.repeat = repeat; +module.exports.extend = extend; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/dumper.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/dumper.js new file mode 100644 index 000000000..2385f569b --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/dumper.js @@ -0,0 +1,437 @@ +'use strict'; + + +var common = require('./common'); +var NIL = common.NIL; +var YAMLException = require('./exception'); +var DEFAULT_SCHEMA = require('./schema/default'); +var SAFE_SCHEMA = require('./schema/safe'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +var CHAR_TAB = 0x09; /* Tab */ +var CHAR_LINE_FEED = 0x0A; /* LF */ +var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */ +var CHAR_SPACE = 0x20; /* Space */ +var CHAR_EXCLAMATION = 0x21; /* ! */ +var CHAR_DOUBLE_QUOTE = 0x22; /* " */ +var CHAR_SHARP = 0x23; /* # */ +var CHAR_PERCENT = 0x25; /* % */ +var CHAR_AMPERSAND = 0x26; /* & */ +var CHAR_SINGLE_QUOTE = 0x27; /* ' */ +var CHAR_ASTERISK = 0x2A; /* * */ +var CHAR_COMMA = 0x2C; /* , */ +var CHAR_MINUS = 0x2D; /* - */ +var CHAR_COLON = 0x3A; /* : */ +var CHAR_GREATER_THAN = 0x3E; /* > */ +var CHAR_QUESTION = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT = 0x40; /* @ */ +var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ +var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ +var CHAR_GRAVE_ACCENT = 0x60; /* ` */ +var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ +var CHAR_VERTICAL_LINE = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ + + +var ESCAPE_SEQUENCES = {}; + +ESCAPE_SEQUENCES[0x00] = '\\0'; +ESCAPE_SEQUENCES[0x07] = '\\a'; +ESCAPE_SEQUENCES[0x08] = '\\b'; +ESCAPE_SEQUENCES[0x09] = '\\t'; +ESCAPE_SEQUENCES[0x0A] = '\\n'; +ESCAPE_SEQUENCES[0x0B] = '\\v'; +ESCAPE_SEQUENCES[0x0C] = '\\f'; +ESCAPE_SEQUENCES[0x0D] = '\\r'; +ESCAPE_SEQUENCES[0x1B] = '\\e'; +ESCAPE_SEQUENCES[0x22] = '\\"'; +ESCAPE_SEQUENCES[0x5C] = '\\\\'; +ESCAPE_SEQUENCES[0x85] = '\\N'; +ESCAPE_SEQUENCES[0xA0] = '\\_'; +ESCAPE_SEQUENCES[0x2028] = '\\L'; +ESCAPE_SEQUENCES[0x2029] = '\\P'; + + +function kindOf(object) { + var kind = typeof object; + + if (null === object) { + return 'null'; + } else if ('number' === kind) { + return 0 === object % 1 ? 'integer' : 'float'; + } else if ('object' === kind && Array.isArray(object)) { + return 'array'; + } else { + return kind; + } +} + + +function compileStyleMap(schema, map) { + var result, keys, index, length, tag, style, type; + + if (null === map) { + return {}; + } + + result = {}; + keys = Object.keys(map); + + for (index = 0, length = keys.length; index < length; index += 1) { + tag = keys[index]; + style = String(map[tag]); + + if ('!!' === tag.slice(0, 2)) { + tag = 'tag:yaml.org,2002:' + tag.slice(2); + } + + type = schema.compiledTypeMap[tag]; + + if (type && type.dumper) { + if (_hasOwnProperty.call(type.dumper.styleAliases, style)) { + style = type.dumper.styleAliases[style]; + } + } + + result[tag] = style; + } + + return result; +} + + +function encodeHex(character) { + var string, handle, length; + + string = character.toString(16).toUpperCase(); + + if (character <= 0xFF) { + handle = 'x'; + length = 2; + } else if (character <= 0xFFFF) { + handle = 'u'; + length = 4; + } else if (character <= 0xFFFFFFFF) { + handle = 'U'; + length = 8; + } else { + throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF'); + } + + return '\\' + handle + common.repeat('0', length - string.length) + string; +} + + +function dump(input, options) { + options = options || {}; + + var schema = options['schema'] || DEFAULT_SCHEMA, + indent = Math.max(1, (options['indent'] || 2)), + flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']), + styleMap = compileStyleMap(schema, options['styles'] || null), + + implicitTypes = schema.compiledImplicit, + explicitTypes = schema.compiledExplicit, + + kind, + tag, + result; + + function generateNextLine(level) { + return '\n' + common.repeat(' ', indent * level); + } + + function testImplicitResolving(object) { + var index, length, type; + + for (index = 0, length = implicitTypes.length; index < length; index += 1) { + type = implicitTypes[index]; + + if (null !== type.loader && + NIL !== type.loader.resolver(object, false)) { + return true; + } + } + + return false; + } + + function writeScalar(object) { + var isQuoted, checkpoint, position, length, character; + + result = ''; + isQuoted = false; + checkpoint = 0; + + if (0 === object.length || + CHAR_SPACE === object.charCodeAt(0) || + CHAR_SPACE === object.charCodeAt(object.length - 1)) { + isQuoted = true; + } + + for (position = 0, length = object.length; position < length; position += 1) { + character = object.charCodeAt(position); + + if (!isQuoted) { + if (CHAR_TAB === character || + CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character || + CHAR_COMMA === character || + CHAR_LEFT_SQUARE_BRACKET === character || + CHAR_RIGHT_SQUARE_BRACKET === character || + CHAR_LEFT_CURLY_BRACKET === character || + CHAR_RIGHT_CURLY_BRACKET === character || + CHAR_SHARP === character || + CHAR_AMPERSAND === character || + CHAR_ASTERISK === character || + CHAR_EXCLAMATION === character || + CHAR_VERTICAL_LINE === character || + CHAR_GREATER_THAN === character || + CHAR_SINGLE_QUOTE === character || + CHAR_DOUBLE_QUOTE === character || + CHAR_PERCENT === character || + CHAR_COMMERCIAL_AT === character || + CHAR_GRAVE_ACCENT === character || + CHAR_QUESTION === character || + CHAR_COLON === character || + CHAR_MINUS === character) { + isQuoted = true; + } + } + + if (ESCAPE_SEQUENCES[character] || + !((0x00020 <= character && character <= 0x00007E) || + (0x00085 === character) || + (0x000A0 <= character && character <= 0x00D7FF) || + (0x0E000 <= character && character <= 0x00FFFD) || + (0x10000 <= character && character <= 0x10FFFF))) { + result += object.slice(checkpoint, position); + result += ESCAPE_SEQUENCES[character] || encodeHex(character); + checkpoint = position + 1; + isQuoted = true; + } + } + + if (checkpoint < position) { + result += object.slice(checkpoint, position); + } + + if (!isQuoted && testImplicitResolving(result)) { + isQuoted = true; + } + + if (isQuoted) { + result = '"' + result + '"'; + } + } + + function writeFlowSequence(level, object) { + var _result = '', + _tag = tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + if (0 !== index) { + _result += ', '; + } + + writeNode(level, object[index], false, false); + _result += result; + } + + tag = _tag; + result = '[' + _result + ']'; + } + + function writeBlockSequence(level, object, compact) { + var _result = '', + _tag = tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + if (!compact || 0 !== index) { + _result += generateNextLine(level); + } + + writeNode(level + 1, object[index], true, true); + _result += '- ' + result; + } + + tag = _tag; + result = _result; + } + + function writeFlowMapping(level, object) { + var _result = '', + _tag = tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + if (0 !== index) { + _result += ', '; + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + writeNode(level, objectKey, false, false); + + if (result.length > 1024) { + _result += '? '; + } + + _result += result + ': '; + writeNode(level, objectValue, false, false); + _result += result; + } + + tag = _tag; + result = '{' + _result + '}'; + } + + function writeBlockMapping(level, object, compact) { + var _result = '', + _tag = tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + explicitPair; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + if (!compact || 0 !== index) { + _result += generateNextLine(level); + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + writeNode(level + 1, objectKey, true, true); + explicitPair = (null !== tag && '?' !== tag && result.length <= 1024); + + if (explicitPair) { + _result += '? '; + } + + _result += result; + + if (explicitPair) { + _result += generateNextLine(level); + } + + writeNode(level + 1, objectValue, true, explicitPair); + _result += ': ' + result; + } + + tag = _tag; + result = _result; + } + + function detectType(object, explicit) { + var _result, typeList, index, length, type, style; + + typeList = explicit ? explicitTypes : implicitTypes; + kind = kindOf(object); + + for (index = 0, length = typeList.length; index < length; index += 1) { + type = typeList[index]; + + if ((null !== type.dumper) && + (null === type.dumper.kind || kind === type.dumper.kind) && + (null === type.dumper.instanceOf || object instanceof type.dumper.instanceOf) && + (null === type.dumper.predicate || type.dumper.predicate(object))) { + tag = explicit ? type.tag : '?'; + + if (null !== type.dumper.representer) { + style = styleMap[type.tag] || type.dumper.defaultStyle; + + if ('function' === typeof type.dumper.representer) { + _result = type.dumper.representer(object, style); + } else if (_hasOwnProperty.call(type.dumper.representer, style)) { + _result = type.dumper.representer[style](object, style); + } else { + throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style'); + } + + if (NIL !== _result) { + kind = kindOf(_result); + result = _result; + } else { + if (explicit) { + throw new YAMLException('cannot represent an object of !<' + type.tag + '> type'); + } else { + continue; + } + } + } + + return true; + } + } + + return false; + } + + function writeNode(level, object, block, compact) { + tag = null; + result = object; + + if (!detectType(object, false)) { + detectType(object, true); + } + + if (block) { + block = (0 > flowLevel || flowLevel > level); + } + + if ((null !== tag && '?' !== tag) || (2 !== indent && level > 0)) { + compact = false; + } + + if ('object' === kind) { + if (block && (0 !== Object.keys(result).length)) { + writeBlockMapping(level, result, compact); + } else { + writeFlowMapping(level, result); + } + } else if ('array' === kind) { + if (block && (0 !== result.length)) { + writeBlockSequence(level, result, compact); + } else { + writeFlowSequence(level, result); + } + } else if ('string' === kind) { + if ('?' !== tag) { + writeScalar(result); + } + } else { + throw new YAMLException('unacceptabe kind of an object to dump (' + kind + ')'); + } + + if (null !== tag && '?' !== tag) { + result = '!<' + tag + '> ' + result; + } + } + + writeNode(0, input, true, true); + return result + '\n'; +} + + +function safeDump(input, options) { + return dump(input, common.extend({ schema: SAFE_SCHEMA }, options)); +} + + +module.exports.dump = dump; +module.exports.safeDump = safeDump; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/exception.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/exception.js new file mode 100644 index 000000000..479ba8879 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/exception.js @@ -0,0 +1,25 @@ +'use strict'; + + +function YAMLException(reason, mark) { + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = this.toString(false); +} + + +YAMLException.prototype.toString = function toString(compact) { + var result; + + result = 'JS-YAML: ' + (this.reason || '(unknown reason)'); + + if (!compact && this.mark) { + result += ' ' + this.mark.toString(); + } + + return result; +}; + + +module.exports = YAMLException; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/loader.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/loader.js new file mode 100644 index 000000000..bdc71d1e0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/loader.js @@ -0,0 +1,1549 @@ +'use strict'; + + +var common = require('./common'); +var YAMLException = require('./exception'); +var Mark = require('./mark'); +var NIL = common.NIL; +var SAFE_SCHEMA = require('./schema/safe'); +var DEFAULT_SCHEMA = require('./schema/default'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +var KIND_STRING = 'string'; +var KIND_ARRAY = 'array'; +var KIND_OBJECT = 'object'; + + +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; + + +var CHOMPING_CLIP = 1; +var CHOMPING_STRIP = 2; +var CHOMPING_KEEP = 3; + + +var CHAR_TAB = 0x09; /* Tab */ +var CHAR_LINE_FEED = 0x0A; /* LF */ +var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */ +var CHAR_SPACE = 0x20; /* Space */ +var CHAR_EXCLAMATION = 0x21; /* ! */ +var CHAR_DOUBLE_QUOTE = 0x22; /* " */ +var CHAR_SHARP = 0x23; /* # */ +var CHAR_PERCENT = 0x25; /* % */ +var CHAR_AMPERSAND = 0x26; /* & */ +var CHAR_SINGLE_QUOTE = 0x27; /* ' */ +var CHAR_ASTERISK = 0x2A; /* * */ +var CHAR_PLUS = 0x2B; /* + */ +var CHAR_COMMA = 0x2C; /* , */ +var CHAR_MINUS = 0x2D; /* - */ +var CHAR_DOT = 0x2E; /* . */ +var CHAR_SLASH = 0x2F; /* / */ +var CHAR_DIGIT_ZERO = 0x30; /* 0 */ +var CHAR_DIGIT_ONE = 0x31; /* 1 */ +var CHAR_DIGIT_NINE = 0x39; /* 9 */ +var CHAR_COLON = 0x3A; /* : */ +var CHAR_LESS_THAN = 0x3C; /* < */ +var CHAR_GREATER_THAN = 0x3E; /* > */ +var CHAR_QUESTION = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT = 0x40; /* @ */ +var CHAR_CAPITAL_A = 0x41; /* A */ +var CHAR_CAPITAL_F = 0x46; /* F */ +var CHAR_CAPITAL_L = 0x4C; /* L */ +var CHAR_CAPITAL_N = 0x4E; /* N */ +var CHAR_CAPITAL_P = 0x50; /* P */ +var CHAR_CAPITAL_U = 0x55; /* U */ +var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ +var CHAR_BACKSLASH = 0x5C; /* \ */ +var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ +var CHAR_UNDERSCORE = 0x5F; /* _ */ +var CHAR_GRAVE_ACCENT = 0x60; /* ` */ +var CHAR_SMALL_A = 0x61; /* a */ +var CHAR_SMALL_B = 0x62; /* b */ +var CHAR_SMALL_E = 0x65; /* e */ +var CHAR_SMALL_F = 0x66; /* f */ +var CHAR_SMALL_N = 0x6E; /* n */ +var CHAR_SMALL_R = 0x72; /* r */ +var CHAR_SMALL_T = 0x74; /* t */ +var CHAR_SMALL_U = 0x75; /* u */ +var CHAR_SMALL_V = 0x76; /* v */ +var CHAR_SMALL_X = 0x78; /* x */ +var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ +var CHAR_VERTICAL_LINE = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ + + +var SIMPLE_ESCAPE_SEQUENCES = {}; + +SIMPLE_ESCAPE_SEQUENCES[CHAR_DIGIT_ZERO] = '\x00'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_A] = '\x07'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_B] = '\x08'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_T] = '\x09'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_TAB] = '\x09'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_N] = '\x0A'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_V] = '\x0B'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_F] = '\x0C'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_R] = '\x0D'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_E] = '\x1B'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SPACE] = ' '; +SIMPLE_ESCAPE_SEQUENCES[CHAR_DOUBLE_QUOTE] = '\x22'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_SLASH] = '/'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_BACKSLASH] = '\x5C'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_N] = '\x85'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_UNDERSCORE] = '\xA0'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_L] = '\u2028'; +SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_P] = '\u2029'; + + +var HEXADECIMAL_ESCAPE_SEQUENCES = {}; + +HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_SMALL_X] = 2; +HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_SMALL_U] = 4; +HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_CAPITAL_U] = 8; + + +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uD800-\uDFFF\uFFFE\uFFFF]/; +var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; +var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + + +function loadAll(input, output, options) { + options = options || {}; + + var filename = options['filename'] || null, + schema = options['schema'] || DEFAULT_SCHEMA, + resolve = options['resolve'] || true, + validate = options['validate'] || true, + strict = options['strict'] || false, + legacy = options['legacy'] || false, + + directiveHandlers = {}, + implicitTypes = schema.compiledImplicit, + typeMap = schema.compiledTypeMap, + + length = input.length, + position = 0, + line = 0, + lineStart = 0, + lineIndent = 0, + character = input.charCodeAt(position), + + version, + checkLineBreaks, + tagMap, + anchorMap, + tag, + anchor, + kind, + result; + + function generateError(message) { + return new YAMLException( + message, + new Mark(filename, input, position, line, (position - lineStart))); + } + + function throwError(message) { + throw generateError(message); + } + + function throwWarning(message) { + var error = generateError(message); + + if (strict) { + throw error; + } else { + console.warn(error.toString()); + } + } + + directiveHandlers['YAML'] = function handleYamlDirective(name, args) { + var match, major, minor; + + if (null !== version) { + throwError('duplication of %YAML directive'); + } + + if (1 !== args.length) { + throwError('YAML directive accepts exactly one argument'); + } + + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + + if (null === match) { + throwError('ill-formed argument of the YAML directive'); + } + + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); + + if (1 !== major) { + throwError('unacceptable YAML version of the document'); + } + + version = args[0]; + checkLineBreaks = (minor < 2); + + if (1 !== minor && 2 !== minor) { + throwWarning('unsupported YAML version of the document'); + } + }; + + directiveHandlers['TAG'] = function handleTagDirective(name, args) { + var handle, prefix; + + if (2 !== args.length) { + throwError('TAG directive accepts exactly two arguments'); + } + + handle = args[0]; + prefix = args[1]; + + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError('ill-formed tag handle (first argument) of the TAG directive'); + } + + if (_hasOwnProperty.call(tagMap, handle)) { + throwError('there is a previously declared suffix for "' + handle + '" tag handle'); + } + + if (!PATTERN_TAG_URI.test(prefix)) { + throwError('ill-formed tag prefix (second argument) of the TAG directive'); + } + + tagMap[handle] = prefix; + }; + + function captureSegment(start, end, checkJson) { + var _position, _length, _character, _result; + + if (start < end) { + _result = input.slice(start, end); + + if (checkJson && validate) { + for (_position = 0, _length = _result.length; + _position < _length; + _position += 1) { + _character = _result.charCodeAt(_position); + if (!(0x09 === _character || + 0x20 <= _character && _character <= 0x10FFFF)) { + throwError('expected valid JSON character'); + } + } + } + + result += _result; + } + } + + function mergeMappings(destination, source) { + var sourceKeys, key, index, quantity; + + if (!common.isObject(source)) { + throwError('cannot merge mappings; the provided source object is unacceptable'); + } + + sourceKeys = Object.keys(source); + + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; + + if (!_hasOwnProperty.call(destination, key)) { + destination[key] = source[key]; + } + } + } + + function storeMappingPair(_result, keyTag, keyNode, valueNode) { + var index, quantity; + + keyNode = String(keyNode); + + if (null === _result) { + _result = {}; + } + + if ('tag:yaml.org,2002:merge' === keyTag) { + if (Array.isArray(valueNode)) { + for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings(_result, valueNode[index]); + } + } else { + mergeMappings(_result, valueNode); + } + } else { + _result[keyNode] = valueNode; + } + + return _result; + } + + function readLineBreak() { + if (CHAR_LINE_FEED === character) { + position += 1; + } else if (CHAR_CARRIAGE_RETURN === character) { + if (CHAR_LINE_FEED === input.charCodeAt(position + 1)) { + position += 2; + } else { + position += 1; + } + } else { + throwError('a line break is expected'); + } + + line += 1; + lineStart = position; + character = input.charCodeAt(position); + } + + function skipSeparationSpace(allowComments, checkIndent) { + var lineBreaks = 0; + + while (position < length) { + while (CHAR_SPACE === character || CHAR_TAB === character) { + character = input.charCodeAt(++position); + } + + if (allowComments && CHAR_SHARP === character) { + do { character = input.charCodeAt(++position); } + while (position < length && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character); + } + + if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { + readLineBreak(); + lineBreaks += 1; + lineIndent = 0; + + while (CHAR_SPACE === character) { + lineIndent += 1; + character = input.charCodeAt(++position); + } + + if (lineIndent < checkIndent) { + throwWarning('deficient indentation'); + } + } else { + break; + } + } + + return lineBreaks; + } + + function testDocumentSeparator() { + var _position, _character; + + if (position === lineStart && + (CHAR_MINUS === character || CHAR_DOT === character) && + input.charCodeAt(position + 1) === character && + input.charCodeAt(position + 2) === character) { + + _position = position + 3; + _character = input.charCodeAt(_position); + + if (_position >= length || + CHAR_SPACE === _character || + CHAR_TAB === _character || + CHAR_LINE_FEED === _character || + CHAR_CARRIAGE_RETURN === _character) { + return true; + } + } + + return false; + } + + function writeFoldedLines(count) { + if (1 === count) { + result += ' '; + } else if (count > 1) { + result += common.repeat('\n', count - 1); + } + } + + function readPlainScalar(nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = kind, + _result = result; + + if (CHAR_SPACE === character || + CHAR_TAB === character || + CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character || + CHAR_COMMA === character || + CHAR_LEFT_SQUARE_BRACKET === character || + CHAR_RIGHT_SQUARE_BRACKET === character || + CHAR_LEFT_CURLY_BRACKET === character || + CHAR_RIGHT_CURLY_BRACKET === character || + CHAR_SHARP === character || + CHAR_AMPERSAND === character || + CHAR_ASTERISK === character || + CHAR_EXCLAMATION === character || + CHAR_VERTICAL_LINE === character || + CHAR_GREATER_THAN === character || + CHAR_SINGLE_QUOTE === character || + CHAR_DOUBLE_QUOTE === character || + CHAR_PERCENT === character || + CHAR_COMMERCIAL_AT === character || + CHAR_GRAVE_ACCENT === character) { + return false; + } + + if (CHAR_QUESTION === character || + CHAR_MINUS === character) { + following = input.charCodeAt(position + 1); + + if (CHAR_SPACE === following || + CHAR_TAB === following || + CHAR_LINE_FEED === following || + CHAR_CARRIAGE_RETURN === following || + withinFlowCollection && + (CHAR_COMMA === following || + CHAR_LEFT_SQUARE_BRACKET === following || + CHAR_RIGHT_SQUARE_BRACKET === following || + CHAR_LEFT_CURLY_BRACKET === following || + CHAR_RIGHT_CURLY_BRACKET === following)) { + return false; + } + } + + kind = KIND_STRING; + result = ''; + captureStart = captureEnd = position; + hasPendingContent = false; + + while (position < length) { + if (CHAR_COLON === character) { + following = input.charCodeAt(position + 1); + + if (CHAR_SPACE === following || + CHAR_TAB === following || + CHAR_LINE_FEED === following || + CHAR_CARRIAGE_RETURN === following || + withinFlowCollection && + (CHAR_COMMA === following || + CHAR_LEFT_SQUARE_BRACKET === following || + CHAR_RIGHT_SQUARE_BRACKET === following || + CHAR_LEFT_CURLY_BRACKET === following || + CHAR_RIGHT_CURLY_BRACKET === following)) { + break; + } + + } else if (CHAR_SHARP === character) { + preceding = input.charCodeAt(position - 1); + + if (CHAR_SPACE === preceding || + CHAR_TAB === preceding || + CHAR_LINE_FEED === preceding || + CHAR_CARRIAGE_RETURN === preceding) { + break; + } + + } else if ((position === lineStart && testDocumentSeparator()) || + withinFlowCollection && + (CHAR_COMMA === character || + CHAR_LEFT_SQUARE_BRACKET === character || + CHAR_RIGHT_SQUARE_BRACKET === character || + CHAR_LEFT_CURLY_BRACKET === character || + CHAR_RIGHT_CURLY_BRACKET === character)) { + break; + + } else if (CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character) { + _line = line; + _lineStart = lineStart; + _lineIndent = lineIndent; + skipSeparationSpace(false, -1); + + if (lineIndent >= nodeIndent) { + hasPendingContent = true; + continue; + } else { + position = captureEnd; + line = _line; + lineStart = _lineStart; + lineIndent = _lineIndent; + character = input.charCodeAt(position); + break; + } + } + + if (hasPendingContent) { + captureSegment(captureStart, captureEnd, false); + writeFoldedLines(line - _line); + captureStart = captureEnd = position; + hasPendingContent = false; + } + + if (CHAR_SPACE !== character && CHAR_TAB !== character) { + captureEnd = position + 1; + } + + character = input.charCodeAt(++position); + } + + captureSegment(captureStart, captureEnd, false); + + if (result) { + return true; + } else { + kind = _kind; + result = _result; + return false; + } + } + + function readSingleQuotedScalar(nodeIndent) { + var captureStart, captureEnd; + + if (CHAR_SINGLE_QUOTE !== character) { + return false; + } + + kind = KIND_STRING; + result = ''; + character = input.charCodeAt(++position); + captureStart = captureEnd = position; + + while (position < length) { + if (CHAR_SINGLE_QUOTE === character) { + captureSegment(captureStart, position, true); + character = input.charCodeAt(++position); + + if (CHAR_SINGLE_QUOTE === character) { + captureStart = captureEnd = position; + character = input.charCodeAt(++position); + } else { + return true; + } + + } else if (CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character) { + captureSegment(captureStart, captureEnd, true); + writeFoldedLines(skipSeparationSpace(false, nodeIndent)); + captureStart = captureEnd = position; + character = input.charCodeAt(position); + + } else if (position === lineStart && testDocumentSeparator()) { + throwError('unexpected end of the document within a single quoted scalar'); + + } else { + character = input.charCodeAt(++position); + captureEnd = position; + } + } + + throwError('unexpected end of the stream within a single quoted scalar'); + } + + function readDoubleQuotedScalar(nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexIndex, + hexOffset, + hexResult; + + if (CHAR_DOUBLE_QUOTE !== character) { + return false; + } + + kind = KIND_STRING; + result = ''; + character = input.charCodeAt(++position); + captureStart = captureEnd = position; + + while (position < length) { + if (CHAR_DOUBLE_QUOTE === character) { + captureSegment(captureStart, position, true); + character = input.charCodeAt(++position); + return true; + + } else if (CHAR_BACKSLASH === character) { + captureSegment(captureStart, position, true); + character = input.charCodeAt(++position); + + if (CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character) { + skipSeparationSpace(false, nodeIndent); + + } else if (SIMPLE_ESCAPE_SEQUENCES[character]) { + result += SIMPLE_ESCAPE_SEQUENCES[character]; + character = input.charCodeAt(++position); + + } else if (HEXADECIMAL_ESCAPE_SEQUENCES[character]) { + hexLength = HEXADECIMAL_ESCAPE_SEQUENCES[character]; + hexResult = 0; + + for (hexIndex = 1; hexIndex <= hexLength; hexIndex += 1) { + hexOffset = (hexLength - hexIndex) * 4; + character = input.charCodeAt(++position); + + if (CHAR_DIGIT_ZERO <= character && character <= CHAR_DIGIT_NINE) { + hexResult |= (character - CHAR_DIGIT_ZERO) << hexOffset; + + } else if (CHAR_CAPITAL_A <= character && character <= CHAR_CAPITAL_F) { + hexResult |= (character - CHAR_CAPITAL_A + 10) << hexOffset; + + } else if (CHAR_SMALL_A <= character && character <= CHAR_SMALL_F) { + hexResult |= (character - CHAR_SMALL_A + 10) << hexOffset; + + } else { + throwError('expected hexadecimal character'); + } + } + + result += String.fromCharCode(hexResult); + character = input.charCodeAt(++position); + + } else { + throwError('unknown escape sequence'); + } + + captureStart = captureEnd = position; + + } else if (CHAR_LINE_FEED === character || + CHAR_CARRIAGE_RETURN === character) { + captureSegment(captureStart, captureEnd, true); + writeFoldedLines(skipSeparationSpace(false, nodeIndent)); + captureStart = captureEnd = position; + character = input.charCodeAt(position); + + } else if (position === lineStart && testDocumentSeparator()) { + throwError('unexpected end of the document within a double quoted scalar'); + + } else { + character = input.charCodeAt(++position); + captureEnd = position; + } + } + + throwError('unexpected end of the stream within a double quoted scalar'); + } + + function readFlowCollection(nodeIndent) { + var readNext = true, + _line, + _tag = tag, + _result, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + keyNode, + keyTag, + valueNode; + + switch (character) { + case CHAR_LEFT_SQUARE_BRACKET: + terminator = CHAR_RIGHT_SQUARE_BRACKET; + isMapping = false; + _result = []; + break; + + case CHAR_LEFT_CURLY_BRACKET: + terminator = CHAR_RIGHT_CURLY_BRACKET; + isMapping = true; + _result = {}; + break; + + default: + return false; + } + + if (null !== anchor) { + anchorMap[anchor] = _result; + } + + character = input.charCodeAt(++position); + + while (position < length) { + skipSeparationSpace(true, nodeIndent); + + if (character === terminator) { + character = input.charCodeAt(++position); + tag = _tag; + kind = isMapping ? KIND_OBJECT : KIND_ARRAY; + result = _result; + return true; + } else if (!readNext) { + throwError('missed comma between flow collection entries'); + } + + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + + if (CHAR_QUESTION === character) { + following = input.charCodeAt(position + 1); + + if (CHAR_SPACE === following || + CHAR_TAB === following || + CHAR_LINE_FEED === following || + CHAR_CARRIAGE_RETURN === following) { + isPair = isExplicitPair = true; + position += 1; + character = following; + skipSeparationSpace(true, nodeIndent); + } + } + + _line = line; + composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = tag; + keyNode = result; + + if ((isExplicitPair || line === _line) && CHAR_COLON === character) { + isPair = true; + character = input.charCodeAt(++position); + skipSeparationSpace(true, nodeIndent); + composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true); + valueNode = result; + } + + if (isMapping) { + storeMappingPair(_result, keyTag, keyNode, valueNode); + } else if (isPair) { + _result.push(storeMappingPair(null, keyTag, keyNode, valueNode)); + } else { + _result.push(keyNode); + } + + skipSeparationSpace(true, nodeIndent); + + if (CHAR_COMMA === character) { + readNext = true; + character = input.charCodeAt(++position); + } else { + readNext = false; + } + } + + throwError('unexpected end of the stream within a flow collection'); + } + + function readBlockScalar(nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = -1; + + switch (character) { + case CHAR_VERTICAL_LINE: + folding = false; + break; + + case CHAR_GREATER_THAN: + folding = true; + break; + + default: + return false; + } + + kind = KIND_STRING; + result = ''; + + while (position < length) { + character = input.charCodeAt(++position); + + if (CHAR_PLUS === character || CHAR_MINUS === character) { + if (CHOMPING_CLIP === chomping) { + chomping = (CHAR_PLUS === character) ? CHOMPING_KEEP : CHOMPING_STRIP; + } else { + throwError('repeat of a chomping mode identifier'); + } + + } else if (CHAR_DIGIT_ZERO <= character && character <= CHAR_DIGIT_NINE) { + if (CHAR_DIGIT_ZERO === character) { + throwError('bad explicit indentation width of a block scalar; it cannot be less than one'); + } else if (!detectedIndent) { + textIndent = nodeIndent + (character - CHAR_DIGIT_ONE); + detectedIndent = true; + } else { + throwError('repeat of an indentation width identifier'); + } + + } else { + break; + } + } + + if (CHAR_SPACE === character || CHAR_TAB === character) { + do { character = input.charCodeAt(++position); } + while (CHAR_SPACE === character || CHAR_TAB === character); + + if (CHAR_SHARP === character) { + do { character = input.charCodeAt(++position); } + while (position < length && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character); + } + } + + while (position < length) { + readLineBreak(); + lineIndent = 0; + + while ((!detectedIndent || lineIndent < textIndent) && + (CHAR_SPACE === character)) { + lineIndent += 1; + character = input.charCodeAt(++position); + } + + if (!detectedIndent && lineIndent > textIndent) { + textIndent = lineIndent; + } + + if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { + emptyLines += 1; + continue; + } + + // End of the scalar. Perform the chomping. + if (lineIndent < textIndent) { + if (CHOMPING_KEEP === chomping) { + result += common.repeat('\n', emptyLines + 1); + } else if (CHOMPING_CLIP === chomping) { + result += '\n'; + } + break; + } + + detectedIndent = true; + + if (folding) { + if (CHAR_SPACE === character || CHAR_TAB === character) { + result += common.repeat('\n', emptyLines + 1); + emptyLines = 1; + } else if (0 === emptyLines) { + result += ' '; + emptyLines = 0; + } else { + result += common.repeat('\n', emptyLines); + emptyLines = 0; + } + } else { + result += common.repeat('\n', emptyLines + 1); + emptyLines = 0; + } + + captureStart = position; + + do { character = input.charCodeAt(++position); } + while (position < length && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character); + + captureSegment(captureStart, position, false); + } + + return true; + } + + function readBlockSequence(nodeIndent) { + var _line, + _tag = tag, + _result = [], + following, + detected = false; + + if (null !== anchor) { + anchorMap[anchor] = _result; + } + + while (position < length) { + if (CHAR_MINUS !== character) { + break; + } + + following = input.charCodeAt(position + 1); + + if (CHAR_SPACE !== following && + CHAR_TAB !== following && + CHAR_LINE_FEED !== following && + CHAR_CARRIAGE_RETURN !== following) { + break; + } + + detected = true; + position += 1; + character = following; + + if (skipSeparationSpace(true, -1)) { + if (lineIndent <= nodeIndent) { + _result.push(null); + continue; + } + } + + _line = line; + composeNode(nodeIndent, CONTEXT_BLOCK_IN, false, true); + _result.push(result); + skipSeparationSpace(true, -1); + + if ((line === _line || lineIndent > nodeIndent) && position < length) { + throwError('bad indentation of a sequence entry'); + } else if (lineIndent < nodeIndent) { + break; + } + } + + if (detected) { + tag = _tag; + kind = KIND_ARRAY; + result = _result; + return true; + } else { + return false; + } + } + + function readBlockMapping(nodeIndent) { + var following, + allowCompact, + _line, + _tag = tag, + _result = {}, + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false; + + if (null !== anchor) { + anchorMap[anchor] = _result; + } + + while (position < length) { + following = input.charCodeAt(position + 1); + _line = line; // Save the current line. + + if ((CHAR_QUESTION === character || + CHAR_COLON === character) && + (CHAR_SPACE === following || + CHAR_TAB === following || + CHAR_LINE_FEED === following || + CHAR_CARRIAGE_RETURN === following)) { + + if (CHAR_QUESTION === character) { + if (atExplicitKey) { + storeMappingPair(_result, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = true; + allowCompact = true; + + } else if (atExplicitKey) { + // i.e. CHAR_COLON === character after the explicit key. + atExplicitKey = false; + allowCompact = true; + + } else { + throwError('incomplete explicit mapping pair; a key node is missed'); + } + + position += 1; + character = following; + + } else if (composeNode(nodeIndent, CONTEXT_FLOW_OUT, false, true)) { + if (line === _line) { + // TODO: Remove this cycle when the flow readers will consume + // trailing whitespaces like the block readers. + while (CHAR_SPACE === character || + CHAR_TAB === character) { + character = input.charCodeAt(++position); + } + + if (CHAR_COLON === character) { + character = input.charCodeAt(++position); + + if (CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character) { + throwError('a whitespace character is expected after the key-value separator within a block mapping'); + } + + if (atExplicitKey) { + storeMappingPair(_result, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = tag; + keyNode = result; + + } else if (detected) { + throwError('can not read an implicit mapping pair; a colon is missed'); + + } else { + tag = _tag; + return true; // Keep the result of `composeNode`. + } + + } else if (detected) { + throwError('can not read a block mapping entry; a multiline key may not be an implicit key'); + + } else { + tag = _tag; + return true; // Keep the result of `composeNode`. + } + + } else { + break; + } + + if (line === _line || lineIndent > nodeIndent) { + if (composeNode(nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = result; + } else { + valueNode = result; + } + } + + if (!atExplicitKey) { + storeMappingPair(_result, keyTag, keyNode, valueNode); + keyTag = keyNode = valueNode = null; + } + + // TODO: It is needed only for flow node readers. It should be removed + // when the flow readers will consume trailing whitespaces as well as + // the block readers. + skipSeparationSpace(true, -1); + } + + if (lineIndent > nodeIndent && position < length) { + throwError('bad indentation of a mapping entry'); + } else if (lineIndent < nodeIndent) { + break; + } + } + + if (atExplicitKey) { + storeMappingPair(_result, keyTag, keyNode, null); + } + + if (detected) { + tag = _tag; + kind = KIND_OBJECT; + result = _result; + } + + return detected; + } + + function readTagProperty() { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName; + + if (CHAR_EXCLAMATION !== character) { + return false; + } + + if (null !== tag) { + throwError('duplication of a tag property'); + } + + character = input.charCodeAt(++position); + + if (CHAR_LESS_THAN === character) { + isVerbatim = true; + character = input.charCodeAt(++position); + + } else if (CHAR_EXCLAMATION === character) { + isNamed = true; + tagHandle = '!!'; + character = input.charCodeAt(++position); + + } else { + tagHandle = '!'; + } + + _position = position; + + if (isVerbatim) { + do { character = input.charCodeAt(++position); } + while (position < length && CHAR_GREATER_THAN !== character); + + if (position < length) { + tagName = input.slice(_position, position); + character = input.charCodeAt(++position); + } else { + throwError('unexpected end of the stream within a verbatim tag'); + } + } else { + while (position < length && + CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character) { + + if (CHAR_EXCLAMATION === character) { + if (!isNamed) { + tagHandle = input.slice(_position - 1, position + 1); + + if (validate && !PATTERN_TAG_HANDLE.test(tagHandle)) { + throwError('named tag handle cannot contain such characters'); + } + + isNamed = true; + _position = position + 1; + } else { + throwError('tag suffix cannot contain exclamation marks'); + } + } + + character = input.charCodeAt(++position); + } + + tagName = input.slice(_position, position); + + if (validate && PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError('tag suffix cannot contain flow indicator characters'); + } + } + + if (validate && tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError('tag name cannot contain such characters: ' + tagName); + } + + if (isVerbatim) { + tag = tagName; + + } else if (_hasOwnProperty.call(tagMap, tagHandle)) { + tag = tagMap[tagHandle] + tagName; + + } else if ('!' === tagHandle) { + tag = '!' + tagName; + + } else if ('!!' === tagHandle) { + tag = 'tag:yaml.org,2002:' + tagName; + + } else { + throwError('undeclared tag handle "' + tagHandle + '"'); + } + + return true; + } + + function readAnchorProperty() { + var _position; + + if (CHAR_AMPERSAND !== character) { + return false; + } + + if (null !== anchor) { + throwError('duplication of an anchor property'); + } + + character = input.charCodeAt(++position); + _position = position; + + while (position < length && + CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character && + CHAR_COMMA !== character && + CHAR_LEFT_SQUARE_BRACKET !== character && + CHAR_RIGHT_SQUARE_BRACKET !== character && + CHAR_LEFT_CURLY_BRACKET !== character && + CHAR_RIGHT_CURLY_BRACKET !== character) { + character = input.charCodeAt(++position); + } + + if (position === _position) { + throwError('name of an anchor node must contain at least one character'); + } + + anchor = input.slice(_position, position); + return true; + } + + function readAlias() { + var _position, alias; + + if (CHAR_ASTERISK !== character) { + return false; + } + + character = input.charCodeAt(++position); + _position = position; + + while (position < length && + CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character && + CHAR_COMMA !== character && + CHAR_LEFT_SQUARE_BRACKET !== character && + CHAR_RIGHT_SQUARE_BRACKET !== character && + CHAR_LEFT_CURLY_BRACKET !== character && + CHAR_RIGHT_CURLY_BRACKET !== character) { + character = input.charCodeAt(++position); + } + + if (position === _position) { + throwError('name of an alias node must contain at least one character'); + } + + alias = input.slice(_position, position); + + if (!anchorMap.hasOwnProperty(alias)) { + throwError('unidentified alias "' + alias + '"'); + } + + result = anchorMap[alias]; + skipSeparationSpace(true, -1); + return true; + } + + function composeNode(parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + atNewLine = false, + isIndented = true, + hasContent = false, + typeIndex, + typeQuantity, + type, + typeLoader, + flowIndent, + blockIndent, + _result; + + tag = null; + anchor = null; + kind = null; + result = null; + + allowBlockStyles = allowBlockScalars = allowBlockCollections = + CONTEXT_BLOCK_OUT === nodeContext || + CONTEXT_BLOCK_IN === nodeContext; + + if (allowToSeek) { + if (skipSeparationSpace(true, -1)) { + atNewLine = true; + + if (lineIndent === parentIndent) { + isIndented = false; + + } else if (lineIndent > parentIndent) { + isIndented = true; + + } else { + return false; + } + } + } + + if (isIndented) { + while (readTagProperty() || readAnchorProperty()) { + if (skipSeparationSpace(true, -1)) { + atNewLine = true; + + if (lineIndent > parentIndent) { + isIndented = true; + allowBlockCollections = allowBlockStyles; + + } else if (lineIndent === parentIndent) { + isIndented = false; + allowBlockCollections = allowBlockStyles; + + } else { + return true; + } + } else { + allowBlockCollections = false; + } + } + } + + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + + if (isIndented || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } + + blockIndent = position - lineStart; + + if (isIndented) { + if (allowBlockCollections && + (readBlockSequence(blockIndent) || + readBlockMapping(blockIndent)) || + readFlowCollection(flowIndent)) { + hasContent = true; + } else { + if ((allowBlockScalars && readBlockScalar(flowIndent)) || + readSingleQuotedScalar(flowIndent) || + readDoubleQuotedScalar(flowIndent)) { + hasContent = true; + + } else if (readAlias()) { + hasContent = true; + + if (null !== tag || null !== anchor) { + throwError('alias node should not have any properties'); + } + + } else if (readPlainScalar(flowIndent, CONTEXT_FLOW_IN === nodeContext)) { + hasContent = true; + + if (null === tag) { + tag = '?'; + } + } + + if (null !== anchor) { + anchorMap[anchor] = result; + } + } + } else { + hasContent = allowBlockCollections && readBlockSequence(blockIndent); + } + } + + if (null !== tag && '!' !== tag) { + if ('?' === tag) { + if (resolve) { + for (typeIndex = 0, typeQuantity = implicitTypes.length; + typeIndex < typeQuantity; + typeIndex += 1) { + type = implicitTypes[typeIndex]; + + // Implicit resolving is not allowed for non-scalar types, and '?' + // non-specific tag is only assigned to plain scalars. So, it isn't + // needed to check for 'kind' conformity. + _result = type.loader.resolver(result, false); + + if (NIL !== _result) { + tag = type.tag; + result = _result; + break; + } + } + } + } else if (_hasOwnProperty.call(typeMap, tag)) { + typeLoader = typeMap[tag].loader; + + if (null !== result && typeLoader.kind !== kind) { + throwError('unacceptable node kind for !<' + tag + '> tag; it should be "' + typeLoader.kind + '", not "' + kind + '"'); + } + + if (typeLoader.resolver) { + _result = typeLoader.resolver(result, true); + + if (NIL !== _result) { + result = _result; + } else { + throwError('cannot resolve a node with !<' + tag + '> explicit tag'); + } + } + } else { + throwWarning('unknown tag !<' + tag + '>'); + } + } + + return null !== tag || null !== anchor || hasContent; + } + + function readDocument() { + var documentStart = position, + _position, + directiveName, + directiveArgs, + hasDirectives = false; + + version = null; + checkLineBreaks = legacy; + tagMap = {}; + anchorMap = {}; + + while (position < length) { + skipSeparationSpace(true, -1); + + if (lineIndent > 0 || CHAR_PERCENT !== character) { + break; + } + + hasDirectives = true; + character = input.charCodeAt(++position); + _position = position; + + while (position < length && + CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character) { + character = input.charCodeAt(++position); + } + + directiveName = input.slice(_position, position); + directiveArgs = []; + + if (directiveName.length < 1) { + throwError('directive name must not be less than one character in length'); + } + + while (position < length) { + while (CHAR_SPACE === character || CHAR_TAB === character) { + character = input.charCodeAt(++position); + } + + if (CHAR_SHARP === character) { + do { character = input.charCodeAt(++position); } + while (position < length && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character); + break; + } + + if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { + break; + } + + _position = position; + + while (position < length && + CHAR_SPACE !== character && + CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character) { + character = input.charCodeAt(++position); + } + + directiveArgs.push(input.slice(_position, position)); + } + + if (position < length) { + readLineBreak(); + } + + if (_hasOwnProperty.call(directiveHandlers, directiveName)) { + directiveHandlers[directiveName](directiveName, directiveArgs); + } else { + throwWarning('unknown document directive "' + directiveName + '"'); + } + } + + skipSeparationSpace(true, -1); + + if (0 === lineIndent && + CHAR_MINUS === character && + CHAR_MINUS === input.charCodeAt(position + 1) && + CHAR_MINUS === input.charCodeAt(position + 2)) { + position += 3; + character = input.charCodeAt(position); + skipSeparationSpace(true, -1); + + } else if (hasDirectives) { + throwError('directives end mark is expected'); + } + + composeNode(lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(true, -1); + + if (validate && checkLineBreaks && + PATTERN_NON_ASCII_LINE_BREAKS.test(input.slice(documentStart, position))) { + throwWarning('non-ASCII line breaks are interpreted as content'); + } + + output(result); + + if (position === lineStart && testDocumentSeparator()) { + if (CHAR_DOT === character) { + position += 3; + character = input.charCodeAt(position); + skipSeparationSpace(true, -1); + } + return; + } + + if (position < length) { + throwError('end of the stream or a document separator is expected'); + } else { + return; + } + } + + if (validate && PATTERN_NON_PRINTABLE.test(input)) { + throwError('the stream contains non-printable characters'); + } + + while (CHAR_SPACE === character) { + lineIndent += 1; + character = input.charCodeAt(++position); + } + + while (position < length) { + readDocument(); + } +} + + +function load(input, options) { + var result = null, received = false; + + function callback(data) { + if (!received) { + result = data; + received = true; + } else { + throw new YAMLException('expected a single document in the stream, but found more'); + } + } + + loadAll(input, callback, options); + + return result; +} + + +function safeLoadAll(input, output, options) { + loadAll(input, output, common.extend({ schema: SAFE_SCHEMA }, options)); +} + + +function safeLoad(input, options) { + return load(input, common.extend({ schema: SAFE_SCHEMA }, options)); +} + + +module.exports.loadAll = loadAll; +module.exports.load = load; +module.exports.safeLoadAll = safeLoadAll; +module.exports.safeLoad = safeLoad; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/mark.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/mark.js new file mode 100644 index 000000000..bfe279ba5 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/mark.js @@ -0,0 +1,78 @@ +'use strict'; + + +var common = require('./common'); + + +function Mark(name, buffer, position, line, column) { + this.name = name; + this.buffer = buffer; + this.position = position; + this.line = line; + this.column = column; +} + + +Mark.prototype.getSnippet = function getSnippet(indent, maxLength) { + var head, start, tail, end, snippet; + + if (!this.buffer) { + return null; + } + + indent = indent || 4; + maxLength = maxLength || 75; + + head = ''; + start = this.position; + + while (start > 0 && -1 === '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1))) { + start -= 1; + if (this.position - start > (maxLength / 2 - 1)) { + head = ' ... '; + start += 5; + break; + } + } + + tail = ''; + end = this.position; + + while (end < this.buffer.length && -1 === '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end))) { + end += 1; + if (end - this.position > (maxLength / 2 - 1)) { + tail = ' ... '; + end -= 5; + break; + } + } + + snippet = this.buffer.slice(start, end); + + return common.repeat(' ', indent) + head + snippet + tail + '\n' + + common.repeat(' ', indent + this.position - start + head.length) + '^'; +}; + + +Mark.prototype.toString = function toString(compact) { + var snippet, where = ''; + + if (this.name) { + where += 'in "' + this.name + '" '; + } + + where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1); + + if (!compact) { + snippet = this.getSnippet(); + + if (snippet) { + where += ':\n' + snippet; + } + } + + return where; +}; + + +module.exports = Mark; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/require.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/require.js new file mode 100644 index 000000000..47b77e31d --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/require.js @@ -0,0 +1,23 @@ +'use strict'; + + +var fs = require('fs'); +var loader = require('./loader'); + + +function yamlRequireHandler(module, filename) { + var content = fs.readFileSync(filename, 'utf8'); + + // fill in documents + module.exports = loader.load(content, { filename: filename }); +} + +// register require extensions only if we're on node.js +// hack for browserify +if (undefined !== require.extensions) { + require.extensions['.yml'] = yamlRequireHandler; + require.extensions['.yaml'] = yamlRequireHandler; +} + + +module.exports = require; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema.js new file mode 100644 index 000000000..ce2139126 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema.js @@ -0,0 +1,103 @@ +'use strict'; + + +var common = require('./common'); +var YAMLException = require('./exception'); +var Type = require('./type'); + + +function compileList(schema, name, result) { + var exclude = []; + + schema.include.forEach(function (includedSchema) { + result = compileList(includedSchema, name, result); + }); + + schema[name].forEach(function (currentType) { + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag) { + exclude.push(previousIndex); + } + }); + + result.push(currentType); + }); + + return result.filter(function (type, index) { + return -1 === exclude.indexOf(index); + }); +} + + +function compileMap(/* lists... */) { + var result = {}, index, length; + + function collectType(type) { + result[type.tag] = type; + } + + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + + return result; +} + + +function Schema(definition) { + this.include = definition.include || []; + this.implicit = definition.implicit || []; + this.explicit = definition.explicit || []; + + this.implicit.forEach(function (type) { + if (null !== type.loader && 'string' !== type.loader.kind) { + throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } + }); + + this.compiledImplicit = compileList(this, 'implicit', []); + this.compiledExplicit = compileList(this, 'explicit', []); + this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit); +} + + +Schema.DEFAULT = null; + + +Schema.create = function createSchema() { + var schemas, types; + + switch (arguments.length) { + case 1: + schemas = Schema.DEFAULT; + types = arguments[0]; + break; + + case 2: + schemas = arguments[0]; + types = arguments[1]; + break; + + default: + throw new YAMLException('Wrong number of arguments for Schema.create function'); + } + + schemas = common.toArray(schemas); + types = common.toArray(types); + + if (!schemas.every(function (schema) { return schema instanceof Schema; })) { + throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.'); + } + + if (!types.every(function (type) { return type instanceof Type; })) { + throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + + return new Schema({ + include: schemas, + explicit: types + }); +}; + + +module.exports = Schema; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/default.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/default.js new file mode 100644 index 000000000..71bb3fcca --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/default.js @@ -0,0 +1,16 @@ +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = Schema.DEFAULT = new Schema({ + include: [ + require('./safe') + ], + explicit: [ + require('../type/js/undefined'), + require('../type/js/regexp'), + require('../type/js/function') + ] +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/minimal.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/minimal.js new file mode 100644 index 000000000..7a6ebbec7 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/minimal.js @@ -0,0 +1,13 @@ +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + explicit: [ + require('../type/str'), + require('../type/seq'), + require('../type/map') + ] +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/safe.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/safe.js new file mode 100644 index 000000000..856b7c415 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/schema/safe.js @@ -0,0 +1,25 @@ +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./minimal') + ], + implicit: [ + require('../type/null'), + require('../type/bool'), + require('../type/int'), + require('../type/float'), + require('../type/timestamp'), + require('../type/merge') + ], + explicit: [ + require('../type/binary'), + require('../type/omap'), + require('../type/pairs'), + require('../type/set') + ] +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type.js new file mode 100644 index 000000000..e0124f2c1 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type.js @@ -0,0 +1,82 @@ +'use strict'; + + +var YAMLException = require('./exception'); + + +// TODO: Add tag format check. +function Type(tag, options) { + options = options || {}; + + this.tag = tag; + this.loader = options['loader'] || null; + this.dumper = options['dumper'] || null; + + if (null === this.loader && null === this.dumper) { + throw new YAMLException('Incomplete YAML type definition. "loader" or "dumper" setting must be specified.'); + } + + if (null !== this.loader) { + this.loader = new Type.Loader(this.loader); + } + + if (null !== this.dumper) { + this.dumper = new Type.Dumper(this.dumper); + } +} + + +Type.Loader = function TypeLoader(options) { + options = options || {}; + + this.kind = options['kind'] || null; + this.resolver = options['resolver'] || null; + + if ('string' !== this.kind && + 'array' !== this.kind && + 'object' !== this.kind) { + throw new YAMLException('Unacceptable "kind" setting of a type loader.'); + } +}; + + +function compileAliases(map) { + var result = {}; + + if (null !== map) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } + + return result; +} + + +Type.Dumper = function TypeDumper(options) { + options = options || {}; + + this.kind = options['kind'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.instanceOf = options['instanceOf'] || null; + this.predicate = options['predicate'] || null; + this.representer = options['representer'] || null; + this.styleAliases = compileAliases(options['styleAliases'] || null); + + if ('undefined' !== this.kind && + 'null' !== this.kind && + 'boolean' !== this.kind && + 'integer' !== this.kind && + 'float' !== this.kind && + 'string' !== this.kind && + 'array' !== this.kind && + 'object' !== this.kind && + 'function' !== this.kind) { + throw new YAMLException('Unacceptable "kind" setting of a type dumper.'); + } +}; + + +module.exports = Type; diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/binary.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/binary.js new file mode 100644 index 000000000..37b4bc70f --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/binary.js @@ -0,0 +1,118 @@ +// Modified from: +// https://raw.github.com/kanaka/noVNC/d890e8640f20fba3215ba7be8e0ff145aeb8c17c/include/base64.js + +'use strict'; + + +var NodeBuffer = require('buffer').Buffer; // A trick for browserified version. +var common = require('../common'); +var NIL = common.NIL; +var Type = require('../type'); + + + +var BASE64_PADDING = '='; + +var BASE64_BINTABLE = [ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 +]; + +var BASE64_CHARTABLE = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + +function resolveYamlBinary(object /*, explicit*/) { + var value, code, idx = 0, result = [], leftbits, leftdata; + + leftbits = 0; // number of bits decoded, but yet to be appended + leftdata = 0; // bits decoded, but yet to be appended + + // Convert one by one. + for (idx = 0; idx < object.length; idx += 1) { + code = object.charCodeAt(idx); + value = BASE64_BINTABLE[code & 0x7F]; + + // Skip LF(NL) || CR + if (0x0A !== code && 0x0D !== code) { + // Fail on illegal characters + if (-1 === value) { + return NIL; + } + + // Collect data into leftdata, update bitcount + leftdata = (leftdata << 6) | value; + leftbits += 6; + + // If we have 8 or more bits, append 8 bits to the result + if (leftbits >= 8) { + leftbits -= 8; + + // Append if not padding. + if (BASE64_PADDING !== object.charAt(idx)) { + result.push((leftdata >> leftbits) & 0xFF); + } + + leftdata &= (1 << leftbits) - 1; + } + } + } + + // If there are any bits left, the base64 string was corrupted + if (leftbits) { + return NIL; + } else { + return new NodeBuffer(result); + } +} + + +function representYamlBinary(object /*, style*/) { + var result = '', index, length, rest; + + // Convert every three bytes to 4 ASCII characters. + for (index = 0, length = object.length - 2; index < length; index += 3) { + result += BASE64_CHARTABLE[object[index + 0] >> 2]; + result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)]; + result += BASE64_CHARTABLE[((object[index + 1] & 0x0F) << 2) + (object[index + 2] >> 6)]; + result += BASE64_CHARTABLE[object[index + 2] & 0x3F]; + } + + rest = object.length % 3; + + // Convert the remaining 1 or 2 bytes, padding out to 4 characters. + if (0 !== rest) { + index = object.length - rest; + result += BASE64_CHARTABLE[object[index + 0] >> 2]; + + if (2 === rest) { + result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)]; + result += BASE64_CHARTABLE[(object[index + 1] & 0x0F) << 2]; + result += BASE64_PADDING; + } else { + result += BASE64_CHARTABLE[(object[index + 0] & 0x03) << 4]; + result += BASE64_PADDING + BASE64_PADDING; + } + } + + return result; +} + + +module.exports = new Type('tag:yaml.org,2002:binary', { + loader: { + kind: 'string', + resolver: resolveYamlBinary + }, + dumper: { + kind: 'object', + instanceOf: NodeBuffer, + representer: representYamlBinary + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/bool.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/bool.js new file mode 100644 index 000000000..987a9e62a --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/bool.js @@ -0,0 +1,74 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var YAML_IMPLICIT_BOOLEAN_MAP = { + 'true' : true, + 'True' : true, + 'TRUE' : true, + 'false' : false, + 'False' : false, + 'FALSE' : false +}; + +var YAML_EXPLICIT_BOOLEAN_MAP = { + 'true' : true, + 'True' : true, + 'TRUE' : true, + 'false' : false, + 'False' : false, + 'FALSE' : false, + 'y' : true, + 'Y' : true, + 'yes' : true, + 'Yes' : true, + 'YES' : true, + 'n' : false, + 'N' : false, + 'no' : false, + 'No' : false, + 'NO' : false, + 'on' : true, + 'On' : true, + 'ON' : true, + 'off' : false, + 'Off' : false, + 'OFF' : false +}; + + +function resolveYamlBoolean(object, explicit) { + if (explicit) { + if (YAML_EXPLICIT_BOOLEAN_MAP.hasOwnProperty(object)) { + return YAML_EXPLICIT_BOOLEAN_MAP[object]; + } else { + return NIL; + } + } else { + if (YAML_IMPLICIT_BOOLEAN_MAP.hasOwnProperty(object)) { + return YAML_IMPLICIT_BOOLEAN_MAP[object]; + } else { + return NIL; + } + } +} + + +module.exports = new Type('tag:yaml.org,2002:bool', { + loader: { + kind: 'string', + resolver: resolveYamlBoolean + }, + dumper: { + kind: 'boolean', + defaultStyle: 'lowercase', + representer: { + lowercase: function (object) { return object ? 'true' : 'false'; }, + uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; }, + camelcase: function (object) { return object ? 'True' : 'False'; } + } + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/float.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/float.js new file mode 100644 index 000000000..edb5fcba3 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/float.js @@ -0,0 +1,102 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var YAML_FLOAT_PATTERN = new RegExp( + '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' + + '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' + + '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' + + '|[-+]?\\.(?:inf|Inf|INF)' + + '|\\.(?:nan|NaN|NAN))$'); + + +function resolveYamlFloat(object /*, explicit*/) { + var value, sign, base, digits; + + if (!YAML_FLOAT_PATTERN.test(object)) { + return NIL; + } + + value = object.replace(/_/g, '').toLowerCase(); + sign = '-' === value[0] ? -1 : 1; + digits = []; + + if (0 <= '+-'.indexOf(value[0])) { + value = value.slice(1); + } + + if ('.inf' === value) { + return (1 === sign) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + + } else if ('.nan' === value) { + return NaN; + + } else if (0 <= value.indexOf(':')) { + value.split(':').forEach(function (v) { + digits.unshift(parseFloat(v, 10)); + }); + + value = 0.0; + base = 1; + + digits.forEach(function (d) { + value += d * base; + base *= 60; + }); + + return sign * value; + + } else { + return sign * parseFloat(value, 10); + } +} + + +function representYamlFloat(object, style) { + if (isNaN(object)) { + switch (style) { + case 'lowercase': + return '.nan'; + case 'uppercase': + return '.NAN'; + case 'camelcase': + return '.NaN'; + } + } else if (Number.POSITIVE_INFINITY === object) { + switch (style) { + case 'lowercase': + return '.inf'; + case 'uppercase': + return '.INF'; + case 'camelcase': + return '.Inf'; + } + } else if (Number.NEGATIVE_INFINITY === object) { + switch (style) { + case 'lowercase': + return '-.inf'; + case 'uppercase': + return '-.INF'; + case 'camelcase': + return '-.Inf'; + } + } else { + return object.toString(10); + } +} + + +module.exports = new Type('tag:yaml.org,2002:float', { + loader: { + kind: 'string', + resolver: resolveYamlFloat + }, + dumper: { + kind: 'float', + defaultStyle: 'lowercase', + representer: representYamlFloat + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/int.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/int.js new file mode 100644 index 000000000..f5e1e7e51 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/int.js @@ -0,0 +1,85 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var YAML_INTEGER_PATTERN = new RegExp( + '^(?:[-+]?0b[0-1_]+' + + '|[-+]?0[0-7_]+' + + '|[-+]?(?:0|[1-9][0-9_]*)' + + '|[-+]?0x[0-9a-fA-F_]+' + + '|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$'); + + +function resolveYamlInteger(object /*, explicit*/) { + var value, sign, base, digits; + + if (!YAML_INTEGER_PATTERN.test(object)) { + return NIL; + } + + value = object.replace(/_/g, ''); + sign = '-' === value[0] ? -1 : 1; + digits = []; + + if (0 <= '+-'.indexOf(value[0])) { + value = value.slice(1); + } + + if ('0' === value) { + return 0; + + } else if (/^0b/.test(value)) { + return sign * parseInt(value.slice(2), 2); + + } else if (/^0x/.test(value)) { + return sign * parseInt(value, 16); + + } else if ('0' === value[0]) { + return sign * parseInt(value, 8); + + } else if (0 <= value.indexOf(':')) { + value.split(':').forEach(function (v) { + digits.unshift(parseInt(v, 10)); + }); + + value = 0; + base = 1; + + digits.forEach(function (d) { + value += (d * base); + base *= 60; + }); + + return sign * value; + + } else { + return sign * parseInt(value, 10); + } +} + + +module.exports = new Type('tag:yaml.org,2002:int', { + loader: { + kind: 'string', + resolver: resolveYamlInteger + }, + dumper: { + kind: 'integer', + defaultStyle: 'decimal', + representer: { + binary: function (object) { return '0b' + object.toString(2); }, + octal: function (object) { return '0' + object.toString(8); }, + decimal: function (object) { return object.toString(10); }, + hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); } + }, + styleAliases: { + binary: [ 2, 'bin' ], + octal: [ 8, 'oct' ], + decimal: [ 10, 'dec' ], + hexadecimal: [ 16, 'hex' ] + } + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/function.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/function.js new file mode 100644 index 000000000..4b3b3ca56 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/function.js @@ -0,0 +1,56 @@ +'use strict'; + + +var esprima = require('esprima'); + + +var NIL = require('../../common').NIL; +var Type = require('../../type'); + + +function resolveJavascriptFunction(object /*, explicit*/) { + /*jslint evil:true*/ + + try { + var source = '(' + object + ')', + ast = esprima.parse(source, { range: true }), + params = [], + body; + + if ('Program' !== ast.type || + 1 !== ast.body.length || + 'ExpressionStatement' !== ast.body[0].type || + 'FunctionExpression' !== ast.body[0].expression.type) { + return NIL; + } + + ast.body[0].expression.params.forEach(function (param) { + params.push(param.name); + }); + + body = ast.body[0].expression.body.range; + + // Esprima's ranges include the first '{' and the last '}' characters on + // function expressions. So cut them out. + return new Function(params, source.slice(body[0]+1, body[1]-1)); + } catch (err) { + return NIL; + } +} + + +function representJavascriptFunction(object /*, style*/) { + return object.toString(); +} + + +module.exports = new Type('tag:yaml.org,2002:js/function', { + loader: { + kind: 'string', + resolver: resolveJavascriptFunction + }, + dumper: { + kind: 'function', + representer: representJavascriptFunction, + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js new file mode 100644 index 000000000..9f4f89e04 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js @@ -0,0 +1,56 @@ +'use strict'; + + +var NIL = require('../../common').NIL; +var Type = require('../../type'); + + +function resolveJavascriptRegExp(object /*, explicit*/) { + var regexp = object, + tail = /\/([gim]*)$/.exec(object), + modifiers; + + // `/foo/gim` - tail can be maximum 4 chars + if ('/' === regexp[0] && tail && 4 >= tail[0].length) { + regexp = regexp.slice(1, regexp.length - tail[0].length); + modifiers = tail[1]; + } + + try { + return new RegExp(regexp, modifiers); + } catch (error) { + return NIL; + } +} + + +function representJavascriptRegExp(object /*, style*/) { + var result = '/' + object.source + '/'; + + if (object.global) { + result += 'g'; + } + + if (object.multiline) { + result += 'm'; + } + + if (object.ignoreCase) { + result += 'i'; + } + + return result; +} + + +module.exports = new Type('tag:yaml.org,2002:js/regexp', { + loader: { + kind: 'string', + resolver: resolveJavascriptRegExp + }, + dumper: { + kind: 'object', + instanceOf: RegExp, + representer: representJavascriptRegExp + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js new file mode 100644 index 000000000..8d2835e19 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js @@ -0,0 +1,28 @@ +'use strict'; + + +var Type = require('../../type'); + + +function resolveJavascriptUndefined(/*object, explicit*/) { + var undef; + + return undef; +} + + +function representJavascriptUndefined(/*object, explicit*/) { + return ''; +} + + +module.exports = new Type('tag:yaml.org,2002:js/undefined', { + loader: { + kind: 'string', + resolver: resolveJavascriptUndefined + }, + dumper: { + kind: 'undefined', + representer: representJavascriptUndefined + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/map.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/map.js new file mode 100644 index 000000000..5cda6de76 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/map.js @@ -0,0 +1,11 @@ +'use strict'; + + +var Type = require('../type'); + + +module.exports = new Type('tag:yaml.org,2002:map', { + loader: { + kind: 'object' + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/merge.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/merge.js new file mode 100644 index 000000000..8facc7080 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/merge.js @@ -0,0 +1,18 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +function resolveYamlMerge(object /*, explicit*/) { + return '<<' === object ? object : NIL; +} + + +module.exports = new Type('tag:yaml.org,2002:merge', { + loader: { + kind: 'string', + resolver: resolveYamlMerge + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/null.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/null.js new file mode 100644 index 000000000..796e1af11 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/null.js @@ -0,0 +1,36 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var YAML_NULL_MAP = { + '~' : true, + 'null' : true, + 'Null' : true, + 'NULL' : true +}; + + +function resolveYamlNull(object /*, explicit*/) { + return YAML_NULL_MAP[object] ? null : NIL; +} + + +module.exports = new Type('tag:yaml.org,2002:null', { + loader: { + kind: 'string', + resolver: resolveYamlNull + }, + dumper: { + kind: 'null', + defaultStyle: 'lowercase', + representer: { + canonical: function () { return '~'; }, + lowercase: function () { return 'null'; }, + uppercase: function () { return 'NULL'; }, + camelcase: function () { return 'Null'; }, + } + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/omap.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/omap.js new file mode 100644 index 000000000..f7c248d4c --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/omap.js @@ -0,0 +1,53 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; +var _toString = Object.prototype.toString; + + +function resolveYamlOmap(object /*, explicit*/) { + var objectKeys = [], index, length, pair, pairKey, pairHasKey; + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + pairHasKey = false; + + if ('[object Object]' !== _toString.call(pair)) { + return NIL; + } + + for (pairKey in pair) { + if (_hasOwnProperty.call(pair, pairKey)) { + if (!pairHasKey) { + pairHasKey = true; + } else { + return NIL; + } + } + } + + if (!pairHasKey) { + return NIL; + } + + if (-1 === objectKeys.indexOf(pairKey)) { + objectKeys.push(pairKey); + } else { + return NIL; + } + } + + return object; +} + + +module.exports = new Type('tag:yaml.org,2002:omap', { + loader: { + kind: 'array', + resolver: resolveYamlOmap + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/pairs.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/pairs.js new file mode 100644 index 000000000..828ff1bb0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/pairs.js @@ -0,0 +1,41 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var _toString = Object.prototype.toString; + + +function resolveYamlPairs(object /*, explicit*/) { + var index, length, pair, keys, result; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + if ('[object Object]' !== _toString.call(pair)) { + return NIL; + } + + keys = Object.keys(pair); + + if (1 !== keys.length) { + return NIL; + } + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return result; +} + + +module.exports = new Type('tag:yaml.org,2002:pairs', { + loader: { + kind: 'array', + resolver: resolveYamlPairs + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/seq.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/seq.js new file mode 100644 index 000000000..80a7cf0fa --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/seq.js @@ -0,0 +1,11 @@ +'use strict'; + + +var Type = require('../type'); + + +module.exports = new Type('tag:yaml.org,2002:seq', { + loader: { + kind: 'array' + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/set.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/set.js new file mode 100644 index 000000000..64bdc6699 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/set.js @@ -0,0 +1,31 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +function resolveYamlSet(object /*, explicit*/) { + var key; + + for (key in object) { + if (_hasOwnProperty.call(object, key)) { + if (null !== object[key]) { + return NIL; + } + } + } + + return object; +} + + +module.exports = new Type('tag:yaml.org,2002:set', { + loader: { + kind: 'object', + resolver: resolveYamlSet + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/str.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/str.js new file mode 100644 index 000000000..384f14e47 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/str.js @@ -0,0 +1,11 @@ +'use strict'; + + +var Type = require('../type'); + + +module.exports = new Type('tag:yaml.org,2002:str', { + loader: { + kind: 'string' + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/timestamp.js b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/timestamp.js new file mode 100644 index 000000000..24da9e2ed --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/lib/js-yaml/type/timestamp.js @@ -0,0 +1,91 @@ +'use strict'; + + +var NIL = require('../common').NIL; +var Type = require('../type'); + + +var YAML_TIMESTAMP_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9]?)' + // [2] month + '-([0-9][0-9]?)' + // [3] day + '(?:(?:[Tt]|[ \\t]+)' + // ... + '([0-9][0-9]?)' + // [4] hour + ':([0-9][0-9])' + // [5] minute + ':([0-9][0-9])' + // [6] second + '(?:\\.([0-9]*))?' + // [7] fraction + '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour + '(?::([0-9][0-9]))?))?)?$'); // [11] tz_minute + + +function resolveYamlTimestamp(object /*, explicit*/) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, data; + + match = YAML_TIMESTAMP_REGEXP.exec(object); + + if (null === match) { + return NIL; + } + + // match: [1] year [2] month [3] day + + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); + + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } + + // match: [4] hour [5] minute [6] second [7] fraction + + hour = +(match[4]); + minute = +(match[5]); + second = +(match[6]); + + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { // milli-seconds + fraction += '0'; + } + fraction = +fraction; + } + + // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute + + if (match[9]) { + tz_hour = +(match[10]); + tz_minute = +(match[11] || 0); + delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds + if ('-' === match[9]) { + delta = -delta; + } + } + + data = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + + if (delta) { + data.setTime(data.getTime() - delta); + } + + return data; +} + + +function representYamlTimestamp(object /*, style*/) { + return object.toISOString(); +} + + +module.exports = new Type('tag:yaml.org,2002:timestamp', { + loader: { + kind: 'string', + resolver: resolveYamlTimestamp + }, + dumper: { + kind: 'object', + instanceOf: Date, + representer: representYamlTimestamp + } +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esparse b/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esparse new file mode 120000 index 000000000..7423b18b2 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esparse @@ -0,0 +1 @@ +../esprima/bin/esparse.js \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esvalidate b/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esvalidate new file mode 120000 index 000000000..16069effb --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/.bin/esvalidate @@ -0,0 +1 @@ +../esprima/bin/esvalidate.js \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/HISTORY.md b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/HISTORY.md new file mode 100644 index 000000000..102f82bf5 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/HISTORY.md @@ -0,0 +1,109 @@ +0.1.15 / 2013-05-13 +------------------- + +* Fixed #55, @trebor89 + + +0.1.14 / 2013-05-12 +------------------- + +* Fixed #62, @maxtaco + + +0.1.13 / 2013-04-08 +------------------- + +* Added `.npmignore` to reduce package size + + +0.1.12 / 2013-02-10 +------------------- + +* Fixed conflictHandler (#46), @hpaulj + + +0.1.11 / 2013-02-07 +------------------- + +* Multiple bugfixes, @hpaulj +* Added 70+ tests (ported from python), @hpaulj +* Added conflictHandler, @applepicke +* Added fromfilePrefixChar, @hpaulj + + +0.1.10 / 2012-12-30 +------------------- + +* Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion) + support, thanks to @hpaulj +* Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj + + +0.1.9 / 2012-12-27 +------------------ + +* Fixed option dest interferens with other options (issue #23), thanks to @hpaulj +* Fixed default value behavior with `*` positionals, thanks to @hpaulj +* Improve `getDefault()` behavior, thanks to @hpaulj +* Imrove negative argument parsing, thanks to @hpaulj + + +0.1.8 / 2012-12-01 +------------------ + +* Fixed parser parents (issue #19), thanks to @hpaulj +* Fixed negative argument parse (issue #20), thanks to @hpaulj + + +0.1.7 / 2012-10-14 +------------------ + +* Fixed 'choices' argument parse (issue #16) +* Fixed stderr output (issue #15) + + +0.1.6 / 2012-09-09 +------------------ + +* Fixed check for conflict of options (thanks to @tomxtobin) + + +0.1.5 / 2012-09-03 +------------------ + +* Fix parser #setDefaults method (thanks to @tomxtobin) + + +0.1.4 / 2012-07-30 +------------------ + +* Fixed pseudo-argument support (thanks to @CGamesPlay) +* Fixed addHelp default (should be true), if not set (thanks to @benblank) + + +0.1.3 / 2012-06-27 +------------------ + +* Fixed formatter api name: Formatter -> HelpFormatter + + +0.1.2 / 2012-05-29 +------------------ + +* Added basic tests +* Removed excess whitespace in help +* Fixed error reporting, when parcer with subcommands + called with empty arguments + + +0.1.1 / 2012-05-23 +------------------ + +* Fixed line wrapping in help formatter +* Added better error reporting on invalid arguments + + +0.1.0 / 2012-05-16 +------------------ + +* First release. diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/LICENSE b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/LICENSE new file mode 100644 index 000000000..1afdae558 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/LICENSE @@ -0,0 +1,21 @@ +(The MIT License) + +Copyright (C) 2012 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/README.md b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/README.md new file mode 100644 index 000000000..f20e0c1f0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/README.md @@ -0,0 +1,239 @@ +argparse +======== + +[![Build Status](https://secure.travis-ci.org/nodeca/argparse.png?branch=master)](http://travis-ci.org/nodeca/argparse) + +CLI arguments parser for node.js. Javascript port of python's +[argparse](http://docs.python.org/dev/library/argparse.html) module +(original version 3.2). That's a full port, except some very rare options, +recorded in issue tracker. + +**NB.** Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/). + + +Example +======= + +test.js file: + +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse example' +}); +parser.addArgument( + [ '-f', '--foo' ], + { + help: 'foo bar' + } +); +parser.addArgument( + [ '-b', '--bar' ], + { + help: 'bar foo' + } +); +var args = parser.parseArgs(); +console.dir(args); +``` + +Display help: + +``` +$ ./test.js -h +usage: example.js [-h] [-v] [-f FOO] [-b BAR] + +Argparse example + +Optional arguments: + -h, --help Show this help message and exit. + -v, --version Show program's version number and exit. + -f FOO, --foo FOO foo bar + -b BAR, --bar BAR bar foo +``` + +Parse arguments: + +``` +$ ./test.js -f=3 --bar=4 +{ foo: '3', bar: '4' } +``` + +More [examples](https://github.com/nodeca/argparse/tree/master/examples). + + +ArgumentParser objects +====================== + +``` +new ArgumentParser({paramters hash}); +``` + +Creates a new ArgumentParser object. + +**Supported params:** + +- ```description``` - Text to display before the argument help. +- ```epilog``` - Text to display after the argument help. +- ```addHelp``` - Add a -h/–help option to the parser. (default: True) +- ```argumentDefault``` - Set the global default value for arguments. (default: None) +- ```parents``` - A list of ArgumentParser objects whose arguments should also be included. +- ```prefixChars``` - The set of characters that prefix optional arguments. (default: ‘-‘) +- ```formatterClass``` - A class for customizing the help output. +- ```prog``` - The name of the program (default: sys.argv[0]) +- ```usage``` - The string describing the program usage (default: generated) +- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals. + +**Not supportied yet** + +- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read. + + +Details in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects) + + +addArgument() method +==================== + +``` +ArgumentParser.addArgument([names or flags], {options}) +``` + +Defines how a single command-line argument should be parsed. + +- ```name or flags``` - Either a name or a list of option strings, e.g. foo or -f, --foo. + +Options: + +- ```action``` - The basic type of action to be taken when this argument is encountered at the command line. +- ```nargs```- The number of command-line arguments that should be consumed. +- ```constant``` - A constant value required by some action and nargs selections. +- ```defaultValue``` - The value produced if the argument is absent from the command line. +- ```type``` - The type to which the command-line argument should be converted. +- ```choices``` - A container of the allowable values for the argument. +- ```required``` - Whether or not the command-line option may be omitted (optionals only). +- ```help``` - A brief description of what the argument does. +- ```metavar``` - A name for the argument in usage messages. +- ```dest``` - The name of the attribute to be added to the object returned by parseArgs(). + +Details in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method) + + +Action (some details) +================ + +ArgumentParser objects associate command-line arguments with actions. +These actions can do just about anything with the command-line arguments associated +with them, though most actions simply add an attribute to the object returned by +parseArgs(). The action keyword argument specifies how the command-line arguments +should be handled. The supported actions are: + +- ```store``` - Just stores the argument’s value. This is the default action. +- ```storeConst``` - Stores value, specified by the const keyword argument. + (Note that the const keyword argument defaults to the rather unhelpful None.) + The 'storeConst' action is most commonly used with optional arguments, that + specify some sort of flag. +- ```storeTrue``` and ```storeFalse``` - Stores values True and False + respectively. These are special cases of 'storeConst'. +- ```append``` - Stores a list, and appends each argument value to the list. + This is useful to allow an option to be specified multiple times. +- ```appendConst``` - Stores a list, and appends value, specified by the + const keyword argument to the list. (Note, that the const keyword argument defaults + is None.) The 'appendConst' action is typically used when multiple arguments need + to store constants to the same list. +- ```count``` - Counts the number of times a keyword argument occurs. For example, + used for increasing verbosity levels. +- ```help``` - Prints a complete help message for all the options in the current + parser and then exits. By default a help action is automatically added to the parser. + See ArgumentParser for details of how the output is created. +- ```version``` - Prints version information and exit. Expects a `version=` + keyword argument in the addArgument() call. + +Details in [original action guide](http://docs.python.org/dev/library/argparse.html#action) + + +Sub-commands +============ + +ArgumentParser.addSubparsers() + +Many programs split their functionality into a number of sub-commands, for +example, the svn program can invoke sub-commands like `svn checkout`, `svn update`, +and `svn commit`. Splitting up functionality this way can be a particularly good +idea when a program performs several different functions which require different +kinds of command-line arguments. `ArgumentParser` supports creation of such +sub-commands with `addSubparsers()` method. The `addSubparsers()` method is +normally called with no arguments and returns an special action object. +This object has a single method `addParser()`, which takes a command name and +any `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object +that can be modified as usual. + +Example: + +sub_commands.js +```javascript +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp:true, + description: 'Argparse examples: sub-commands', +}); + +var subparsers = parser.addSubparsers({ + title:'subcommands', + dest:"subcommand_name" +}); + +var bar = subparsers.addParser('c1', {addHelp:true}); +bar.addArgument( + [ '-f', '--foo' ], + { + action: 'store', + help: 'foo3 bar3' + } +); +var bar = subparsers.addParser( + 'c2', + {aliases:['co'], addHelp:true} +); +bar.addArgument( + [ '-b', '--bar' ], + { + action: 'store', + type: 'int', + help: 'foo3 bar3' + } +); + +var args = parser.parseArgs(); +console.dir(args); + +``` + +Details in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands) + + +Contributors +============ + +- [Eugene Shkuropat](https://github.com/shkuropat) +- [Paul Jacobson](https://github.com/hpaulj) + +[others](https://github.com/nodeca/argparse/graphs/contributors) + +License +======= + +Copyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin). +Released under the MIT license. See +[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details. + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/arguments.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/arguments.js new file mode 100755 index 000000000..5b090fa2e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/arguments.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: arguments' +}); +parser.addArgument( + [ '-f', '--foo' ], + { + help: 'foo bar' + } +); +parser.addArgument( + [ '-b', '--bar' ], + { + help: 'bar foo' + } +); + + +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs('-f 1 -b2'.split(' ')); +console.dir(args); +console.log('-----------'); +args = parser.parseArgs('-f=3 --bar=4'.split(' ')); +console.dir(args); +console.log('-----------'); +args = parser.parseArgs('--foo 5 --bar 6'.split(' ')); +console.dir(args); +console.log('-----------'); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/choice.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/choice.js new file mode 100755 index 000000000..2616fa4d7 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/choice.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: choice' +}); + +parser.addArgument(['foo'], {choices: 'abc'}); + +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs(['c']); +console.dir(args); +console.log('-----------'); +parser.parseArgs(['X']); +console.dir(args); + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/constants.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/constants.js new file mode 100755 index 000000000..172a4f3d4 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/constants.js @@ -0,0 +1,59 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: constant' +}); + +parser.addArgument( + [ '-a'], + { + action: 'storeConst', + dest: 'answer', + help: 'store constant', + constant: 42 + } +); +parser.addArgument( + [ '--str' ], + { + action: 'appendConst', + dest: 'types', + help: 'append constant "str" to types', + constant: 'str' + } +); +parser.addArgument( + [ '--int' ], + { + action: 'appendConst', + dest: 'types', + help: 'append constant "int" to types', + constant: 'int' + } +); + +parser.addArgument( + [ '--true' ], + { + action: 'storeTrue', + help: 'store true constant' + } +); +parser.addArgument( + [ '--false' ], + { + action: 'storeFalse', + help: 'store false constant' + } +); + +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs('-a --str --int --true'.split(' ')); +console.dir(args); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/help.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/help.js new file mode 100755 index 000000000..7eb955534 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/help.js @@ -0,0 +1,13 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: help', + epilog: 'help epilog', + prog: 'help_example_prog', + usage: 'Usage %(prog)s ' +}); +parser.printHelp(); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/nargs.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/nargs.js new file mode 100755 index 000000000..74f376beb --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/nargs.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: nargs' +}); +parser.addArgument( + [ '-f', '--foo' ], + { + help: 'foo bar', + nargs: 1 + } +); +parser.addArgument( + [ '-b', '--bar' ], + { + help: 'bar foo', + nargs: '*' + } +); + +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs('--foo a --bar c d'.split(' ')); +console.dir(args); +console.log('-----------'); +args = parser.parseArgs('--bar b c f --foo a'.split(' ')); +console.dir(args); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/parents.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/parents.js new file mode 100755 index 000000000..dfe896868 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/parents.js @@ -0,0 +1,28 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; + +var args; +var parent_parser = new ArgumentParser({ addHelp: false }); +// note addHelp:false to prevent duplication of the -h option +parent_parser.addArgument( + ['--parent'], + { type: 'int', description: 'parent' } +); + +var foo_parser = new ArgumentParser({ + parents: [ parent_parser ], + description: 'child1' +}); +foo_parser.addArgument(['foo']); +args = foo_parser.parseArgs(['--parent', '2', 'XXX']); +console.log(args); + +var bar_parser = new ArgumentParser({ + parents: [ parent_parser ], + description: 'child2' +}); +bar_parser.addArgument(['--bar']); +args = bar_parser.parseArgs(['--bar', 'YYY']); +console.log(args); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/prefix_chars.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/prefix_chars.js new file mode 100755 index 000000000..430d5e182 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/prefix_chars.js @@ -0,0 +1,23 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: prefix_chars', + prefixChars: '-+' +}); +parser.addArgument(['+f', '++foo']); +parser.addArgument(['++bar'], {action: 'storeTrue'}); + +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs(['+f', '1']); +console.dir(args); +args = parser.parseArgs(['++bar']); +console.dir(args); +args = parser.parseArgs(['++foo', '2', '++bar']); +console.dir(args); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sub_commands.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sub_commands.js new file mode 100755 index 000000000..df9c49444 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sub_commands.js @@ -0,0 +1,49 @@ +#!/usr/bin/env node +'use strict'; + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ + version: '0.0.1', + addHelp: true, + description: 'Argparse examples: sub-commands' +}); + +var subparsers = parser.addSubparsers({ + title: 'subcommands', + dest: "subcommand_name" +}); + +var bar = subparsers.addParser('c1', {addHelp: true, help: 'c1 help'}); +bar.addArgument( + [ '-f', '--foo' ], + { + action: 'store', + help: 'foo3 bar3' + } +); +var bar = subparsers.addParser( + 'c2', + {aliases: ['co'], addHelp: true, help: 'c2 help'} +); +bar.addArgument( + [ '-b', '--bar' ], + { + action: 'store', + type: 'int', + help: 'foo3 bar3' + } +); +parser.printHelp(); +console.log('-----------'); + +var args; +args = parser.parseArgs('c1 -f 2'.split(' ')); +console.dir(args); +console.log('-----------'); +args = parser.parseArgs('c2 -b 1'.split(' ')); +console.dir(args); +console.log('-----------'); +args = parser.parseArgs('co -b 1'.split(' ')); +console.dir(args); +console.log('-----------'); +parser.parseArgs(['c1', '-h']); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sum.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sum.js new file mode 100755 index 000000000..4532800a5 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/sum.js @@ -0,0 +1,35 @@ +#!/usr/bin/env node + +'use strict'; + + +var ArgumentParser = require('../lib/argparse').ArgumentParser; +var parser = new ArgumentParser({ description: 'Process some integers.' }); + + +function sum(arr) { + return arr.reduce(function (a, b) { + return a + b; + }, 0); +} +function max(arr) { + return Math.max.apply(Math, arr); +} + + +parser.addArgument(['integers'], { + metavar: 'N', + type: 'int', + nargs: '+', + help: 'an integer for the accumulator' +}); +parser.addArgument(['--sum'], { + dest: 'accumulate', + action: 'storeConst', + constant: sum, + defaultValue: max, + help: 'sum the integers (default: find the max)' +}); + +var args = parser.parseArgs('--sum 1 2 -1'.split(' ')); +console.log(args.accumulate(args.integers)); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/testformatters.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/testformatters.js new file mode 100644 index 000000000..afb4a2d68 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/examples/testformatters.js @@ -0,0 +1,270 @@ +'use strict'; + +var a, group, parser, helptext; + +var assert = require('assert'); +var _ = require('underscore'); +_.str = require('underscore.string'); +var print = function () { + return console.log.apply(console, arguments); + }; +// print = function () {}; + +var argparse = require('argparse'); + +print("TEST argparse.ArgumentDefaultsHelpFormatter"); + +parser = new argparse.ArgumentParser({ + debug: true, + formatterClass: argparse.ArgumentDefaultsHelpFormatter, + description: 'description' +}); + +parser.addArgument(['--foo'], { + help: 'foo help - oh and by the way, %(defaultValue)s' +}); + +parser.addArgument(['--bar'], { + action: 'storeTrue', + help: 'bar help' +}); + +parser.addArgument(['spam'], { + help: 'spam help' +}); + +parser.addArgument(['badger'], { + nargs: '?', + defaultValue: 'wooden', + help: 'badger help' +}); + +group = parser.addArgumentGroup({ + title: 'title', + description: 'group description' +}); + +group.addArgument(['--baz'], { + type: 'int', + defaultValue: 42, + help: 'baz help' +}); + +helptext = parser.formatHelp(); +print(helptext); +// test selected clips +assert(helptext.match(/badger help \(default: wooden\)/)); +assert(helptext.match(/foo help - oh and by the way, null/)); +assert(helptext.match(/bar help \(default: false\)/)); +assert(helptext.match(/title:\n {2}group description/)); // test indent +assert(helptext.match(/baz help \(default: 42\)/im)); + +/* +usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger] + +description + +positional arguments: + spam spam help + badger badger help (default: wooden) + +optional arguments: + -h, --help show this help message and exit + --foo FOO foo help - oh and by the way, null + --bar bar help (default: false) + +title: + group description + + --baz BAZ baz help (default: 42) +*/ + +print("TEST argparse.RawDescriptionHelpFormatter"); + +parser = new argparse.ArgumentParser({ + debug: true, + prog: 'PROG', + formatterClass: argparse.RawDescriptionHelpFormatter, + description: 'Keep the formatting\n' + + ' exactly as it is written\n' + + '\n' + + 'here\n' +}); + +a = parser.addArgument(['--foo'], { + help: ' foo help should not\n' + + ' retain this odd formatting' +}); + +parser.addArgument(['spam'], { + 'help': 'spam help' +}); + +group = parser.addArgumentGroup({ + title: 'title', + description: ' This text\n' + + ' should be indented\n' + + ' exactly like it is here\n' +}); + +group.addArgument(['--bar'], { + help: 'bar help' +}); + +helptext = parser.formatHelp(); +print(helptext); +// test selected clips +assert(helptext.match(parser.description)); +assert.equal(helptext.match(a.help), null); +assert(helptext.match(/foo help should not retain this odd formatting/)); + +/* +class TestHelpRawDescription(HelpTestCase): + """Test the RawTextHelpFormatter""" +.... + +usage: PROG [-h] [--foo FOO] [--bar BAR] spam + +Keep the formatting + exactly as it is written + +here + +positional arguments: + spam spam help + +optional arguments: + -h, --help show this help message and exit + --foo FOO foo help should not retain this odd formatting + +title: + This text + should be indented + exactly like it is here + + --bar BAR bar help +*/ + + +print("TEST argparse.RawTextHelpFormatter"); + +parser = new argparse.ArgumentParser({ + debug: true, + prog: 'PROG', + formatterClass: argparse.RawTextHelpFormatter, + description: 'Keep the formatting\n' + + ' exactly as it is written\n' + + '\n' + + 'here\n' +}); + +parser.addArgument(['--baz'], { + help: ' baz help should also\n' + + 'appear as given here' +}); + +a = parser.addArgument(['--foo'], { + help: ' foo help should also\n' + + 'appear as given here' +}); + +parser.addArgument(['spam'], { + 'help': 'spam help' +}); + +group = parser.addArgumentGroup({ + title: 'title', + description: ' This text\n' + + ' should be indented\n' + + ' exactly like it is here\n' +}); + +group.addArgument(['--bar'], { + help: 'bar help' +}); + +helptext = parser.formatHelp(); +print(helptext); +// test selected clips +assert(helptext.match(parser.description)); +assert(helptext.match(/( {14})appear as given here/gm)); + +/* +class TestHelpRawText(HelpTestCase): + """Test the RawTextHelpFormatter""" + +usage: PROG [-h] [--foo FOO] [--bar BAR] spam + +Keep the formatting + exactly as it is written + +here + +positional arguments: + spam spam help + +optional arguments: + -h, --help show this help message and exit + --foo FOO foo help should also + appear as given here + +title: + This text + should be indented + exactly like it is here + + --bar BAR bar help +*/ + + +print("TEST metavar as a tuple"); + +parser = new argparse.ArgumentParser({ + prog: 'PROG' +}); + +parser.addArgument(['-w'], { + help: 'w', + nargs: '+', + metavar: ['W1', 'W2'] +}); + +parser.addArgument(['-x'], { + help: 'x', + nargs: '*', + metavar: ['X1', 'X2'] +}); + +parser.addArgument(['-y'], { + help: 'y', + nargs: 3, + metavar: ['Y1', 'Y2', 'Y3'] +}); + +parser.addArgument(['-z'], { + help: 'z', + nargs: '?', + metavar: ['Z1'] +}); + +helptext = parser.formatHelp(); +print(helptext); +var ustring = 'PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] [-z [Z1]]'; +ustring = ustring.replace(/\[/g, '\\[').replace(/\]/g, '\\]'); +// print(ustring) +assert(helptext.match(new RegExp(ustring))); + +/* +class TestHelpTupleMetavar(HelpTestCase): + """Test specifying metavar as a tuple""" + +usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] [-z [Z1]] + +optional arguments: + -h, --help show this help message and exit + -w W1 [W2 ...] w + -x [X1 [X2 ...]] x + -y Y1 Y2 Y3 y + -z [Z1] z +*/ + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/index.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/index.js new file mode 100644 index 000000000..3b6eea013 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/argparse'); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action.js new file mode 100644 index 000000000..6f7e9a56c --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action.js @@ -0,0 +1,146 @@ +/** + * class Action + * + * Base class for all actions + * Do not call in your code, use this class only for inherits your own action + * + * Information about how to convert command line strings to Javascript objects. + * Action objects are used by an ArgumentParser to represent the information + * needed to parse a single argument from one or more strings from the command + * line. The keyword arguments to the Action constructor are also all attributes + * of Action instances. + * + * #####Alowed keywords: + * + * - `store` + * - `storeConstant` + * - `storeTrue` + * - `storeFalse` + * - `append` + * - `appendConstant` + * - `count` + * - `help` + * - `version` + * + * Information about action options see [[Action.new]] + * + * See also [original guide](http://docs.python.org/dev/library/argparse.html#action) + * + **/ + +'use strict'; + + +// Constants +var $$ = require('./const'); + + +/** + * new Action(options) + * + * Base class for all actions. Used only for inherits + * + * + * ##### Options: + * + * - `optionStrings` A list of command-line option strings for the action. + * - `dest` Attribute to hold the created object(s) + * - `nargs` The number of command-line arguments that should be consumed. + * By default, one argument will be consumed and a single value will be + * produced. + * - `constant` Default value for an action with no value. + * - `defaultValue` The value to be produced if the option is not specified. + * - `type` Cast to 'string'|'int'|'float'|'complex'|function (string). If + * None, 'string'. + * - `choices` The choices available. + * - `required` True if the action must always be specified at the command + * line. + * - `help` The help describing the argument. + * - `metavar` The name to be used for the option's argument with the help + * string. If None, the 'dest' value will be used as the name. + * + * ##### nargs supported values: + * + * - `N` (an integer) consumes N arguments (and produces a list) + * - `?` consumes zero or one arguments + * - `*` consumes zero or more arguments (and produces a list) + * - `+` consumes one or more arguments (and produces a list) + * + * Note: that the difference between the default and nargs=1 is that with the + * default, a single value will be produced, while with nargs=1, a list + * containing a single value will be produced. + **/ +var Action = module.exports = function Action(options) { + options = options || {}; + this.optionStrings = options.optionStrings || []; + this.dest = options.dest; + this.nargs = options.nargs !== undefined ? options.nargs : null; + this.constant = options.constant !== undefined ? options.constant : null; + this.defaultValue = options.defaultValue; + this.type = options.type !== undefined ? options.type : null; + this.choices = options.choices !== undefined ? options.choices : null; + this.required = options.required !== undefined ? options.required: false; + this.help = options.help !== undefined ? options.help : null; + this.metavar = options.metavar !== undefined ? options.metavar : null; + + if (!(this.optionStrings instanceof Array)) { + throw new Error('optionStrings should be an array'); + } + if (this.required !== undefined && typeof(this.required) !== 'boolean') { + throw new Error('required should be a boolean'); + } +}; + +/** + * Action#getName -> String + * + * Tells action name + **/ +Action.prototype.getName = function () { + if (this.optionStrings.length > 0) { + return this.optionStrings.join('/'); + } else if (this.metavar !== null && this.metavar !== $$.SUPPRESS) { + return this.metavar; + } else if (this.dest !== undefined && this.dest !== $$.SUPPRESS) { + return this.dest; + } + return null; +}; + +/** + * Action#isOptional -> Boolean + * + * Return true if optional + **/ +Action.prototype.isOptional = function () { + return !this.isPositional(); +}; + +/** + * Action#isPositional -> Boolean + * + * Return true if positional + **/ +Action.prototype.isPositional = function () { + return (this.optionStrings.length === 0); +}; + +/** + * Action#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Should be implemented in inherited classes + * + * ##### Example + * + * ActionCount.prototype.call = function (parser, namespace, values, optionString) { + * namespace.set(this.dest, (namespace[this.dest] || 0) + 1); + * }; + * + **/ +Action.prototype.call = function () { + throw new Error('.call() not defined');// Not Implemented error +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append.js new file mode 100644 index 000000000..48c6dbe30 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append.js @@ -0,0 +1,55 @@ +/*:nodoc:* + * class ActionAppend + * + * This action stores a list, and appends each argument value to the list. + * This is useful to allow an option to be specified multiple times. + * This class inherided from [[Action]] + * + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var $$ = require('../const'); + +/*:nodoc:* + * new ActionAppend(options) + * - options (object): options hash see [[Action.new]] + * + * Note: options.nargs should be optional for constants + * and more then zero for other + **/ +var ActionAppend = module.exports = function ActionAppend(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for append actions must be > 0; if arg ' + + 'strings are not supplying the value to append, ' + + 'the append const action may be more appropriate'); + } + if (!!this.constant && this.nargs !== $$.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionAppend, Action); + +/*:nodoc:* + * ActionAppend#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppend.prototype.call = function (parser, namespace, values) { + var items = [].concat(namespace[this.dest] || []); // or _.clone + items.push(values); + namespace.set(this.dest, items); +}; + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append/constant.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append/constant.js new file mode 100644 index 000000000..90747abbf --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/append/constant.js @@ -0,0 +1,47 @@ +/*:nodoc:* + * class ActionAppendConstant + * + * This stores a list, and appends the value specified by + * the const keyword argument to the list. + * (Note that the const keyword argument defaults to null.) + * The 'appendConst' action is typically useful when multiple + * arguments need to store constants to the same list. + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionAppendConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionAppendConstant = module.exports = function ActionAppendConstant(options) { + options = options || {}; + options.nargs = 0; + if (options.constant === undefined) { + throw new Error('constant option is required for appendAction'); + } + Action.call(this, options); +}; +util.inherits(ActionAppendConstant, Action); + +/*:nodoc:* + * ActionAppendConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionAppendConstant.prototype.call = function (parser, namespace) { + var items = [].concat(namespace[this.dest] || []); + items.push(this.constant); + namespace.set(this.dest, items); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/count.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/count.js new file mode 100644 index 000000000..d6a5899d0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/count.js @@ -0,0 +1,40 @@ +/*:nodoc:* + * class ActionCount + * + * This counts the number of times a keyword argument occurs. + * For example, this is useful for increasing verbosity levels + * + * This class inherided from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +/*:nodoc:* + * new ActionCount(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionCount = module.exports = function ActionCount(options) { + options = options || {}; + options.nargs = 0; + + Action.call(this, options); +}; +util.inherits(ActionCount, Action); + +/*:nodoc:* + * ActionCount#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionCount.prototype.call = function (parser, namespace) { + namespace.set(this.dest, (namespace[this.dest] || 0) + 1); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/help.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/help.js new file mode 100644 index 000000000..7f7b4e2d2 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/help.js @@ -0,0 +1,48 @@ +/*:nodoc:* + * class ActionHelp + * + * Support action for printing help + * This class inherided from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var $$ = require('../const'); + +/*:nodoc:* + * new ActionHelp(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionHelp = module.exports = function ActionHelp(options) { + options = options || {}; + if (options.defaultValue !== null) { + options.defaultValue = options.defaultValue; + } + else { + options.defaultValue = $$.SUPPRESS; + } + options.dest = (options.dest !== null ? options.dest: $$.SUPPRESS); + options.nargs = 0; + Action.call(this, options); + +}; +util.inherits(ActionHelp, Action); + +/*:nodoc:* + * ActionHelp#call(parser, namespace, values, optionString) + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print help and exit + **/ +ActionHelp.prototype.call = function (parser) { + parser.printHelp(); + parser.exit(); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store.js new file mode 100644 index 000000000..8ebc9748b --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store.js @@ -0,0 +1,50 @@ +/*:nodoc:* + * class ActionStore + * + * This action just stores the argument’s value. This is the default action. + * + * This class inherited from [[Action]] + * + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// Constants +var $$ = require('../const'); + + +/*:nodoc:* + * new ActionStore(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStore = module.exports = function ActionStore(options) { + options = options || {}; + if (this.nargs <= 0) { + throw new Error('nargs for store actions must be > 0; if you ' + + 'have nothing to store, actions such as store ' + + 'true or store const may be more appropriate'); + + } + if (this.constant !== undefined && this.nargs !== $$.OPTIONAL) { + throw new Error('nargs must be OPTIONAL to supply const'); + } + Action.call(this, options); +}; +util.inherits(ActionStore, Action); + +/*:nodoc:* + * ActionStore#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStore.prototype.call = function (parser, namespace, values) { + namespace.set(this.dest, values); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/constant.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/constant.js new file mode 100644 index 000000000..8410fcf78 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/constant.js @@ -0,0 +1,43 @@ +/*:nodoc:* + * class ActionStoreConstant + * + * This action stores the value specified by the const keyword argument. + * (Note that the const keyword argument defaults to the rather unhelpful null.) + * The 'store_const' action is most commonly used with optional + * arguments that specify some sort of flag. + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../../action'); + +/*:nodoc:* + * new ActionStoreConstant(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreConstant = module.exports = function ActionStoreConstant(options) { + options = options || {}; + options.nargs = 0; + if (options.constant === undefined) { + throw new Error('constant option is required for storeAction'); + } + Action.call(this, options); +}; +util.inherits(ActionStoreConstant, Action); + +/*:nodoc:* + * ActionStoreConstant#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Save result in namespace object + **/ +ActionStoreConstant.prototype.call = function (parser, namespace) { + namespace.set(this.dest, this.constant); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/false.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/false.js new file mode 100644 index 000000000..66417bf6d --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/false.js @@ -0,0 +1,27 @@ +/*:nodoc:* + * class ActionStoreFalse + * + * This action store the values False respectively. + * This is special cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ + +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreFalse(options) + * - options (object): hash of options see [[Action.new]] + * + **/ +var ActionStoreFalse = module.exports = function ActionStoreFalse(options) { + options = options || {}; + options.constant = false; + options.defaultValue = options.defaultValue !== null ? options.defaultValue: true; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreFalse, ActionStoreConstant); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/true.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/true.js new file mode 100644 index 000000000..43ec7086f --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/store/true.js @@ -0,0 +1,26 @@ +/*:nodoc:* + * class ActionStoreTrue + * + * This action store the values True respectively. + * This isspecial cases of 'storeConst' + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var ActionStoreConstant = require('./constant'); + +/*:nodoc:* + * new ActionStoreTrue(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionStoreTrue = module.exports = function ActionStoreTrue(options) { + options = options || {}; + options.constant = true; + options.defaultValue = options.defaultValue !== null ? options.defaultValue: false; + ActionStoreConstant.call(this, options); +}; +util.inherits(ActionStoreTrue, ActionStoreConstant); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/subparsers.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/subparsers.js new file mode 100644 index 000000000..adecf654a --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/subparsers.js @@ -0,0 +1,148 @@ +/** internal + * class ActionSubparsers + * + * Support the creation of such sub-commands with the addSubparsers() + * + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; +var _ = require('underscore'); + + +var Action = require('../action'); + +// Constants +var $$ = require('../const'); + +// Errors +var argumentErrorHelper = require('../argument/error'); + + +/*:nodoc:* + * new ChoicesPseudoAction(name, help) + * + * Create pseudo action for correct help text + * + **/ +var ChoicesPseudoAction = function (name, help) { + var options = { + optionStrings: [], + dest: name, + help: help + }; + + Action.call(this, options); +}; +util.inherits(ChoicesPseudoAction, Action); + +/** + * new ActionSubparsers(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionSubparsers = module.exports = function ActionSubparsers(options) { + options = options || {}; + options.dest = options.dest || $$.SUPPRESS; + options.nargs = $$.PARSER; + + this.debug = (options.debug === true); + + this._progPrefix = options.prog; + this._parserClass = options.parserClass; + this._nameParserMap = {}; + this._choicesActions = []; + + options.choices = this._nameParserMap; + Action.call(this, options); +}; +util.inherits(ActionSubparsers, Action); + +/*:nodoc:* + * ActionSubparsers#addParser(name, options) -> ArgumentParser + * - name (string): sub-command name + * - options (object): see [[ArgumentParser.new]] + * + * Note: + * addParser supports an additional aliases option, + * which allows multiple strings to refer to the same subparser. + * This example, like svn, aliases co as a shorthand for checkout + * + **/ +ActionSubparsers.prototype.addParser = function (name, options) { + var parser; + + var self = this; + + options = options || {}; + + options.debug = (this.debug === true); + + // set program from the existing prefix + if (!options.prog) { + options.prog = this._progPrefix + ' ' + name; + } + + var aliases = options.aliases || []; + + // create a pseudo-action to hold the choice help + if (!!options.help || _.isString(options.help)) { + var help = options.help; + delete options.help; + + var choiceAction = new ChoicesPseudoAction(name, help); + this._choicesActions.push(choiceAction); + } + + // create the parser and add it to the map + parser = new this._parserClass(options); + this._nameParserMap[name] = parser; + + // make parser available under aliases also + aliases.forEach(function (alias) { + self._nameParserMap[alias] = parser; + }); + + return parser; +}; + +ActionSubparsers.prototype._getSubactions = function () { + return this._choicesActions; +}; + +/*:nodoc:* + * ActionSubparsers#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Call the action. Parse input aguments + **/ +ActionSubparsers.prototype.call = function (parser, namespace, values) { + var parserName = values[0]; + var argStrings = values.slice(1); + + // set the parser name if requested + if (this.dest !== $$.SUPPRESS) { + namespace[this.dest] = parserName; + } + + // select the parser + if (!!this._nameParserMap[parserName]) { + parser = this._nameParserMap[parserName]; + } else { + throw argumentErrorHelper(format( + 'Unknown parser "%s" (choices: [%s]).', + parserName, + _.keys(this._nameParserMap).join(', ') + )); + } + + // parse all the remaining options into the namespace + parser.parseArgs(argStrings, namespace); +}; + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/version.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/version.js new file mode 100644 index 000000000..a17877c0b --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action/version.js @@ -0,0 +1,50 @@ +/*:nodoc:* + * class ActionVersion + * + * Support action for printing program version + * This class inherited from [[Action]] + **/ +'use strict'; + +var util = require('util'); + +var Action = require('../action'); + +// +// Constants +// +var $$ = require('../const'); + +/*:nodoc:* + * new ActionVersion(options) + * - options (object): options hash see [[Action.new]] + * + **/ +var ActionVersion = module.exports = function ActionVersion(options) { + options = options || {}; + options.defaultValue = (!!options.defaultValue ? options.defaultValue: $$.SUPPRESS); + options.dest = (options.dest || $$.SUPPRESS); + options.nargs = 0; + this.version = options.version; + Action.call(this, options); +}; +util.inherits(ActionVersion, Action); + +/*:nodoc:* + * ActionVersion#call(parser, namespace, values, optionString) -> Void + * - parser (ArgumentParser): current parser + * - namespace (Namespace): namespace for output data + * - values (Array): parsed values + * - optionString (Array): input option string(not parsed) + * + * Print version and exit + **/ +ActionVersion.prototype.call = function (parser) { + var version = this.version || parser.version; + var formatter = parser._getFormatter(); + formatter.addText(version); + parser.exit(0, formatter.formatHelp()); +}; + + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action_container.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action_container.js new file mode 100644 index 000000000..dbe3e3c46 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/action_container.js @@ -0,0 +1,481 @@ +/** internal + * class ActionContainer + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + **/ + +'use strict'; + +var format = require('util').format; +var _ = require('underscore'); + +_.str = require('underscore.string'); + +// Constants +var $$ = require('./const'); + +//Actions +var ActionHelp = require('./action/help'); +var ActionAppend = require('./action/append'); +var ActionAppendConstant = require('./action/append/constant'); +var ActionCount = require('./action/count'); +var ActionStore = require('./action/store'); +var ActionStoreConstant = require('./action/store/constant'); +var ActionStoreTrue = require('./action/store/true'); +var ActionStoreFalse = require('./action/store/false'); +var ActionVersion = require('./action/version'); +var ActionSubparsers = require('./action/subparsers'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + + + +/** + * new ActionContainer(options) + * + * Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]] + * + * ##### Options: + * + * - `description` -- A description of what the program does + * - `prefixChars` -- Characters that prefix optional arguments + * - `argumentDefault` -- The default value for all arguments + * - `conflictHandler` -- The conflict handler to use for duplicate arguments + **/ +var ActionContainer = module.exports = function ActionContainer(options) { + options = options || {}; + + this.description = options.description; + this.argumentDefault = options.argumentDefault; + this.prefixChars = options.prefixChars || ''; + this.conflictHandler = options.conflictHandler; + + // set up registries + this._registries = {}; + + // register actions + this.register('action', null, ActionStore); + this.register('action', 'store', ActionStore); + this.register('action', 'storeConst', ActionStoreConstant); + this.register('action', 'storeTrue', ActionStoreTrue); + this.register('action', 'storeFalse', ActionStoreFalse); + this.register('action', 'append', ActionAppend); + this.register('action', 'appendConst', ActionAppendConstant); + this.register('action', 'count', ActionCount); + this.register('action', 'help', ActionHelp); + this.register('action', 'version', ActionVersion); + this.register('action', 'parsers', ActionSubparsers); + + // raise an exception if the conflict handler is invalid + this._getHandler(); + + // action storage + this._actions = []; + this._optionStringActions = {}; + + // groups + this._actionGroups = []; + this._mutuallyExclusiveGroups = []; + + // defaults storage + this._defaults = {}; + + // determines whether an "option" looks like a negative number + // -1, -1.5 -5e+4 + this._regexpNegativeNumber = new RegExp('^[-]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$'); + + // whether or not there are any optionals that look like negative + // numbers -- uses a list so it can be shared and edited + this._hasNegativeNumberOptionals = []; +}; + +// Groups must be required, then ActionContainer already defined +var ArgumentGroup = require('./argument/group'); +var MutuallyExclusiveGroup = require('./argument/exclusive'); + +// +// Registration methods +// + +/** + * ActionContainer#register(registryName, value, object) -> Void + * - registryName (String) : object type action|type + * - value (string) : keyword + * - object (Object|Function) : handler + * + * Register handlers + **/ +ActionContainer.prototype.register = function (registryName, value, object) { + this._registries[registryName] = this._registries[registryName] || {}; + this._registries[registryName][value] = object; +}; + +ActionContainer.prototype._registryGet = function (registryName, value, defaultValue) { + if (3 > arguments.length) { + defaultValue = null; + } + return this._registries[registryName][value] || defaultValue; +}; + +// +// Namespace default accessor methods +// + +/** + * ActionContainer#setDefaults(options) -> Void + * - options (object):hash of options see [[Action.new]] + * + * Set defaults + **/ +ActionContainer.prototype.setDefaults = function (options) { + options = options || {}; + for (var property in options) { + this._defaults[property] = options[property]; + } + + // if these defaults match any existing arguments, replace the previous + // default on the object with the new one + this._actions.forEach(function (action) { + if (action.dest in options) { + action.defaultValue = options[action.dest]; + } + }); +}; + +/** + * ActionContainer#getDefault(dest) -> Mixed + * - dest (string): action destination + * + * Return action default value + **/ +ActionContainer.prototype.getDefault = function (dest) { + var result = (_.has(this._defaults, dest)) ? this._defaults[dest] : null; + + this._actions.forEach(function (action) { + if (action.dest === dest && _.has(action, 'defaultValue')) { + result = action.defaultValue; + } + }); + + return result; +}; +// +// Adding argument actions +// + +/** + * ActionContainer#addArgument(args, options) -> Object + * - args (Array): array of argument keys + * - options (Object): action objects see [[Action.new]] + * + * #### Examples + * - addArgument([-f, --foo], {action:'store', defaultValue=1, ...}) + * - addArgument(['bar'], action: 'store', nargs:1, ...}) + **/ +ActionContainer.prototype.addArgument = function (args, options) { + args = args; + options = options || {}; + + if (!_.isArray(args)) { + throw new TypeError('addArgument first argument should be an array'); + } + if (!_.isObject(options) || _.isArray(options)) { + throw new TypeError('addArgument second argument should be a hash'); + } + + // if no positional args are supplied or only one is supplied and + // it doesn't look like an option string, parse a positional argument + if (!args || args.length === 1 && this.prefixChars.indexOf(args[0][0]) < 0) { + if (args && !!options.dest) { + throw new Error('dest supplied twice for positional argument'); + } + options = this._getPositional(args, options); + + // otherwise, we're adding an optional argument + } else { + options = this._getOptional(args, options); + } + + // if no default was supplied, use the parser-level default + if (_.isUndefined(options.defaultValue)) { + var dest = options.dest; + if (_.has(this._defaults, dest)) { + options.defaultValue = this._defaults[dest]; + } else if (!_.isUndefined(this.argumentDefault)) { + options.defaultValue = this.argumentDefault; + } + } + + // create the action object, and add it to the parser + var ActionClass = this._popActionClass(options); + if (! _.isFunction(ActionClass)) { + throw new Error(format('Unknown action "%s".', ActionClass)); + } + var action = new ActionClass(options); + + // throw an error if the action type is not callable + var typeFunction = this._registryGet('type', action.type, action.type); + if (!_.isFunction(typeFunction)) { + throw new Error(format('"%s" is not callable', typeFunction)); + } + + return this._addAction(action); +}; + +/** + * ActionContainer#addArgumentGroup(options) -> ArgumentGroup + * - options (Object): hash of options see [[ArgumentGroup.new]] + * + * Create new arguments groups + **/ +ActionContainer.prototype.addArgumentGroup = function (options) { + var group = new ArgumentGroup(this, options); + this._actionGroups.push(group); + return group; +}; + +/** + * ActionContainer#addMutuallyExclusiveGroup(options) -> ArgumentGroup + * - options (Object): {required: false} + * + * Create new mutual exclusive groups + **/ +ActionContainer.prototype.addMutuallyExclusiveGroup = function (options) { + var group = new MutuallyExclusiveGroup(this, options); + this._mutuallyExclusiveGroups.push(group); + return group; +}; + +ActionContainer.prototype._addAction = function (action) { + var self = this; + + // resolve any conflicts + this._checkConflict(action); + + // add to actions list + this._actions.push(action); + action.container = this; + + // index the action by any option strings it has + action.optionStrings.forEach(function (optionString) { + self._optionStringActions[optionString] = action; + }); + + // set the flag if any option strings look like negative numbers + action.optionStrings.forEach(function (optionString) { + if (optionString.match(self._regexpNegativeNumber)) { + if (!_.any(self._hasNegativeNumberOptionals)) { + self._hasNegativeNumberOptionals.push(true); + } + } + }); + + // return the created action + return action; +}; + +ActionContainer.prototype._removeAction = function (action) { + var actionIndex = this._actions.indexOf(action); + if (actionIndex >= 0) { + this._actions.splice(actionIndex, 1); + } +}; + +ActionContainer.prototype._addContainerActions = function (container) { + // collect groups by titles + var titleGroupMap = {}; + this._actionGroups.forEach(function (group) { + if (titleGroupMap[group.title]) { + throw new Error(format('Cannot merge actions - two groups are named "%s".', group.title)); + } + titleGroupMap[group.title] = group; + }); + + // map each action to its group + var groupMap = {}; + function actionHash(action) { + // unique (hopefully?) string suitable as dictionary key + return action.getName(); + } + container._actionGroups.forEach(function (group) { + // if a group with the title exists, use that, otherwise + // create a new group matching the container's group + if (!titleGroupMap[group.title]) { + titleGroupMap[group.title] = this.addArgumentGroup({ + title: group.title, + description: group.description + }); + } + + // map the actions to their new group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = titleGroupMap[group.title]; + }); + }, this); + + // add container's mutually exclusive groups + // NOTE: if add_mutually_exclusive_group ever gains title= and + // description= then this code will need to be expanded as above + var mutexGroup; + container._mutuallyExclusiveGroups.forEach(function (group) { + mutexGroup = this.addMutuallyExclusiveGroup({ + required: group.required + }); + // map the actions to their new mutex group + group._groupActions.forEach(function (action) { + groupMap[actionHash(action)] = mutexGroup; + }); + }, this); // forEach takes a 'this' argument + + // add all actions to this container or their group + container._actions.forEach(function (action) { + var key = actionHash(action); + if (!!groupMap[key]) { + groupMap[key]._addAction(action); + } + else + { + this._addAction(action); + } + }); +}; + +ActionContainer.prototype._getPositional = function (dest, options) { + if (_.isArray(dest)) { + dest = _.first(dest); + } + // make sure required is not specified + if (options.required) { + throw new Error('"required" is an invalid argument for positionals.'); + } + + // mark positional arguments as required if at least one is + // always required + if (options.nargs !== $$.OPTIONAL && options.nargs !== $$.ZERO_OR_MORE) { + options.required = true; + } + if (options.nargs === $$.ZERO_OR_MORE && options.defaultValue === undefined) { + options.required = true; + } + + // return the keyword arguments with no option strings + options.dest = dest; + options.optionStrings = []; + return options; +}; + +ActionContainer.prototype._getOptional = function (args, options) { + var prefixChars = this.prefixChars; + var optionStrings = []; + var optionStringsLong = []; + + // determine short and long option strings + args.forEach(function (optionString) { + // error on strings that don't start with an appropriate prefix + if (prefixChars.indexOf(optionString[0]) < 0) { + throw new Error(format('Invalid option string "%s": must start with a "%s".', + optionString, + prefixChars + )); + } + + // strings starting with two prefix characters are long options + optionStrings.push(optionString); + if (optionString.length > 1 && prefixChars.indexOf(optionString[1]) >= 0) { + optionStringsLong.push(optionString); + } + }); + + // infer dest, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' + var dest = options.dest || null; + delete options.dest; + + if (!dest) { + var optionStringDest = optionStringsLong.length ? optionStringsLong[0] :optionStrings[0]; + dest = _.str.strip(optionStringDest, this.prefixChars); + + if (dest.length === 0) { + throw new Error( + format('dest= is required for options like "%s"', optionStrings.join(', ')) + ); + } + dest = dest.replace(/-/g, '_'); + } + + // return the updated keyword arguments + options.dest = dest; + options.optionStrings = optionStrings; + + return options; +}; + +ActionContainer.prototype._popActionClass = function (options, defaultValue) { + defaultValue = defaultValue || null; + + var action = (options.action || defaultValue); + delete options.action; + + var actionClass = this._registryGet('action', action, action); + return actionClass; +}; + +ActionContainer.prototype._getHandler = function () { + var handlerString = this.conflictHandler; + var handlerFuncName = "_handleConflict" + _.str.capitalize(handlerString); + var func = this[handlerFuncName]; + if (typeof func === 'undefined') { + var msg = "invalid conflict resolution value: " + handlerString; + throw new Error(msg); + } else { + return func; + } +}; + +ActionContainer.prototype._checkConflict = function (action) { + var optionStringActions = this._optionStringActions; + var conflictOptionals = []; + + // find all options that conflict with this option + // collect pairs, the string, and an existing action that it conflicts with + action.optionStrings.forEach(function (optionString) { + var conflOptional = optionStringActions[optionString]; + if (typeof conflOptional !== 'undefined') { + conflictOptionals.push([optionString, conflOptional]); + } + }); + + if (conflictOptionals.length > 0) { + var conflictHandler = this._getHandler(); + conflictHandler.call(this, action, conflictOptionals); + } +}; + +ActionContainer.prototype._handleConflictError = function (action, conflOptionals) { + var conflicts = _.map(conflOptionals, function (pair) {return pair[0]; }); + conflicts = conflicts.join(', '); + throw argumentErrorHelper( + action, + format('Conflicting option string(s): %s', conflicts) + ); +}; + +ActionContainer.prototype._handleConflictResolve = function (action, conflOptionals) { + // remove all conflicting options + var self = this; + conflOptionals.forEach(function (pair) { + var optionString = pair[0]; + var conflictingAction = pair[1]; + // remove the conflicting option string + var i = conflictingAction.optionStrings.indexOf(optionString); + if (i >= 0) { + conflictingAction.optionStrings.splice(i, 1); + } + delete self._optionStringActions[optionString]; + // if the option now has no option string, remove it from the + // container holding it + if (conflictingAction.optionStrings.length === 0) { + conflictingAction.container._removeAction(conflictingAction); + } + }); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argparse.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argparse.js new file mode 100644 index 000000000..f2a2c51d9 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argparse.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports.ArgumentParser = require('./argument_parser.js'); +module.exports.Namespace = require('./namespace'); +module.exports.Action = require('./action'); +module.exports.HelpFormatter = require('./help/formatter.js'); +module.exports.Const = require('./const.js'); + +module.exports.ArgumentDefaultsHelpFormatter = + require('./help/added_formatters.js').ArgumentDefaultsHelpFormatter; +module.exports.RawDescriptionHelpFormatter = + require('./help/added_formatters.js').RawDescriptionHelpFormatter; +module.exports.RawTextHelpFormatter = + require('./help/added_formatters.js').RawTextHelpFormatter; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/error.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/error.js new file mode 100644 index 000000000..c8a02a08b --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/error.js @@ -0,0 +1,50 @@ +'use strict'; + + +var format = require('util').format; + + +var ERR_CODE = 'ARGError'; + +/*:nodoc:* + * argumentError(argument, message) -> TypeError + * - argument (Object): action with broken argument + * - message (String): error message + * + * Error format helper. An error from creating or using an argument + * (optional or positional). The string value of this exception + * is the message, augmented with information + * about the argument that caused it. + * + * #####Example + * + * var argumentErrorHelper = require('./argument/error'); + * if (conflictOptionals.length > 0) { + * throw argumentErrorHelper( + * action, + * format('Conflicting option string(s): %s', conflictOptionals.join(', ')) + * ); + * } + * + **/ +module.exports = function (argument, message) { + var argumentName = null; + var errMessage; + var err; + + if (argument.getName) { + argumentName = argument.getName(); + } else { + argumentName = '' + argument; + } + + if (!argumentName) { + errMessage = message; + } else { + errMessage = format('argument "%s": %s', argumentName, message); + } + + err = new TypeError(errMessage); + err.code = ERR_CODE; + return err; +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/exclusive.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/exclusive.js new file mode 100644 index 000000000..8287e00d0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/exclusive.js @@ -0,0 +1,54 @@ +/** internal + * class MutuallyExclusiveGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ArgumentGroup = require('./group'); + +/** + * new MutuallyExclusiveGroup(container, options) + * - container (object): main container + * - options (object): options.required -> true/false + * + * `required` could be an argument itself, but making it a property of + * the options argument is more consistent with the JS adaptation of the Python) + **/ +var MutuallyExclusiveGroup = module.exports = function MutuallyExclusiveGroup(container, options) { + var required; + options = options || {}; + required = options.required || false; + ArgumentGroup.call(this, container); + this.required = required; + +}; +util.inherits(MutuallyExclusiveGroup, ArgumentGroup); + + +MutuallyExclusiveGroup.prototype._addAction = function (action) { + var msg; + if (action.required) { + msg = 'mutually exclusive arguments must be optional'; + throw new Error(msg); + } + action = this._container._addAction(action); + this._groupActions.push(action); + return action; +}; + + +MutuallyExclusiveGroup.prototype._removeAction = function (action) { + this._container._removeAction(action); + this._groupActions.remove(action); +}; + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/group.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/group.js new file mode 100644 index 000000000..58b271f2f --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument/group.js @@ -0,0 +1,75 @@ +/** internal + * class ArgumentGroup + * + * Group arguments. + * By default, ArgumentParser groups command-line arguments + * into “positional arguments” and “optional arguments” + * when displaying help messages. When there is a better + * conceptual grouping of arguments than this default one, + * appropriate groups can be created using the addArgumentGroup() method + * + * This class inherited from [[ArgumentContainer]] + **/ +'use strict'; + +var util = require('util'); + +var ActionContainer = require('../action_container'); + + +/** + * new ArgumentGroup(container, options) + * - container (object): main container + * - options (object): hash of group options + * + * #### options + * - **prefixChars** group name prefix + * - **argumentDefault** default argument value + * - **title** group title + * - **description** group description + * + **/ +var ArgumentGroup = module.exports = function ArgumentGroup(container, options) { + + options = options || {}; + + // add any missing keyword arguments by checking the container + options.conflictHandler = (options.conflictHandler || container.conflictHandler); + options.prefixChars = (options.prefixChars || container.prefixChars); + options.argumentDefault = (options.argumentDefault || container.argumentDefault); + + ActionContainer.call(this, options); + + // group attributes + this.title = options.title; + this._groupActions = []; + + // share most attributes with the container + this._container = container; + this._registries = container._registries; + this._actions = container._actions; + this._optionStringActions = container._optionStringActions; + this._defaults = container._defaults; + this._hasNegativeNumberOptionals = container._hasNegativeNumberOptionals; + this._mutuallyExclusiveGroups = container._mutuallyExclusiveGroups; +}; +util.inherits(ArgumentGroup, ActionContainer); + + +ArgumentGroup.prototype._addAction = function (action) { + // Parent add action + action = ActionContainer.prototype._addAction.call(this, action); + this._groupActions.push(action); + return action; +}; + + +ArgumentGroup.prototype._removeAction = function (action) { + // Parent remove action + ActionContainer.prototype._removeAction.call(this, action); + var actionIndex = this._groupActions.indexOf(action); + if (actionIndex >= 0) { + this._groupActions.splice(actionIndex, 1); + } +}; + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument_parser.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument_parser.js new file mode 100644 index 000000000..97cf09823 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/argument_parser.js @@ -0,0 +1,1165 @@ +/** + * class ArgumentParser + * + * Object for parsing command line strings into js objects. + * + * Inherited from [[ActionContainer]] + **/ +'use strict'; + +var util = require('util'); +var format = require('util').format; +var Path = require('path'); + +var _ = require('underscore'); +_.str = require('underscore.string'); + +// Constants +var $$ = require('./const'); + +var ActionContainer = require('./action_container'); + +// Errors +var argumentErrorHelper = require('./argument/error'); + +var HelpFormatter = require('./help/formatter'); + +var Namespace = require('./namespace'); + + +/** + * new ArgumentParser(options) + * + * Create a new ArgumentParser object. + * + * ##### Options: + * - `prog` The name of the program (default: sys.argv[0]) + * - `usage` A usage message (default: auto-generated from arguments) + * - `description` A description of what the program does + * - `epilog` Text following the argument descriptions + * - `parents` Parsers whose arguments should be copied into this one + * - `formatterClass` HelpFormatter class for printing help messages + * - `prefixChars` Characters that prefix optional arguments + * - `fromfilePrefixChars` Characters that prefix files containing additional arguments + * - `argumentDefault` The default value for all arguments + * - `addHelp` Add a -h/-help option + * - `conflictHandler` Specifies how to handle conflicting argument names + * - `debug` Enable debug mode. Argument errors throw exception in + * debug mode and process.exit in normal. Used for development and + * testing (default: false) + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#argumentparser-objects + **/ +var ArgumentParser = module.exports = function ArgumentParser(options) { + var self = this; + options = options || {}; + + options.description = (options.description || null); + options.argumentDefault = (options.argumentDefault || null); + options.prefixChars = (options.prefixChars || '-'); + options.conflictHandler = (options.conflictHandler || 'error'); + ActionContainer.call(this, options); + + options.addHelp = (options.addHelp === undefined || !!options.addHelp); + options.parents = (options.parents || []); + // default program name + options.prog = (options.prog || Path.basename(process.argv[1])); + this.prog = options.prog; + this.usage = options.usage; + this.epilog = options.epilog; + this.version = options.version; + + this.debug = (options.debug === true); + + this.formatterClass = (options.formatterClass || HelpFormatter); + this.fromfilePrefixChars = options.fromfilePrefixChars || null; + this._positionals = this.addArgumentGroup({title: 'Positional arguments'}); + this._optionals = this.addArgumentGroup({title: 'Optional arguments'}); + this._subparsers = null; + + // register types + var FUNCTION_IDENTITY = function (o) { + return o; + }; + this.register('type', 'auto', FUNCTION_IDENTITY); + this.register('type', null, FUNCTION_IDENTITY); + this.register('type', 'int', function (x) { + var result = parseInt(x, 10); + if (isNaN(result)) { + throw new Error(x + ' is not a valid integer.'); + } + return result; + }); + this.register('type', 'float', function (x) { + var result = parseFloat(x); + if (isNaN(result)) { + throw new Error(x + ' is not a valid float.'); + } + return result; + }); + this.register('type', 'string', function (x) { + return '' + x; + }); + + // add help and version arguments if necessary + var defaultPrefix = (this.prefixChars.indexOf('-') > -1) ? '-' : this.prefixChars[0]; + if (options.addHelp) { + this.addArgument( + [defaultPrefix + 'h', defaultPrefix + defaultPrefix + 'help'], + { + action: 'help', + defaultValue: $$.SUPPRESS, + help: 'Show this help message and exit.' + } + ); + } + if (this.version !== undefined) { + this.addArgument( + [defaultPrefix + 'v', defaultPrefix + defaultPrefix + 'version'], + { + action: 'version', + version: this.version, + defaultValue: $$.SUPPRESS, + help: "Show program's version number and exit." + } + ); + } + + // add parent arguments and defaults + options.parents.forEach(function (parent) { + self._addContainerActions(parent); + if (parent._defaults !== undefined) { + for (var defaultKey in parent._defaults) { + if (parent._defaults.hasOwnProperty(defaultKey)) { + self._defaults[defaultKey] = parent._defaults[defaultKey]; + } + } + } + }); + +}; +util.inherits(ArgumentParser, ActionContainer); + +/** + * ArgumentParser#addSubparsers(options) -> [[ActionSubparsers]] + * - options (object): hash of options see [[ActionSubparsers.new]] + * + * See also [subcommands][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#sub-commands + **/ +ArgumentParser.prototype.addSubparsers = function (options) { + if (!!this._subparsers) { + this.error('Cannot have multiple subparser arguments.'); + } + + options = options || {}; + options.debug = (this.debug === true); + options.optionStrings = []; + options.parserClass = (options.parserClass || ArgumentParser); + + + if (!!options.title || !!options.description) { + + this._subparsers = this.addArgumentGroup({ + title: (options.title || 'subcommands'), + description: options.description + }); + delete options.title; + delete options.description; + + } else { + this._subparsers = this._positionals; + } + + // prog defaults to the usage message of this parser, skipping + // optional arguments and with no "usage:" prefix + if (!options.prog) { + var formatter = this._getFormatter(); + var positionals = this._getPositionalActions(); + var groups = this._mutuallyExclusiveGroups; + formatter.addUsage(this.usage, positionals, groups, ''); + options.prog = _.str.strip(formatter.formatHelp()); + } + + // create the parsers action and add it to the positionals list + var ParsersClass = this._popActionClass(options, 'parsers'); + var action = new ParsersClass(options); + this._subparsers._addAction(action); + + // return the created parsers action + return action; +}; + +ArgumentParser.prototype._addAction = function (action) { + if (action.isOptional()) { + this._optionals._addAction(action); + } else { + this._positionals._addAction(action); + } + return action; +}; + +ArgumentParser.prototype._getOptionalActions = function () { + return this._actions.filter(function (action) { + return action.isOptional(); + }); +}; + +ArgumentParser.prototype._getPositionalActions = function () { + return this._actions.filter(function (action) { + return action.isPositional(); + }); +}; + + +/** + * ArgumentParser#parseArgs(args, namespace) -> Namespace|Object + * - args (array): input elements + * - namespace (Namespace|Object): result object + * + * Parsed args and throws error if some arguments are not recognized + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-parse-args-method + **/ +ArgumentParser.prototype.parseArgs = function (args, namespace) { + var argv; + var result = this.parseKnownArgs(args, namespace); + + args = result[0]; + argv = result[1]; + if (argv && argv.length > 0) { + this.error( + format('Unrecognized arguments: %s.', argv.join(' ')) + ); + } + return args; +}; + +/** + * ArgumentParser#parseKnownArgs(args, namespace) -> array + * - args (array): input options + * - namespace (Namespace|Object): result object + * + * Parse known arguments and return tuple of result object + * and unknown args + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#partial-parsing + **/ +ArgumentParser.prototype.parseKnownArgs = function (args, namespace) { + var self = this; + + // args default to the system args + args = args || process.argv.slice(2); + + // default Namespace built from parser defaults + namespace = namespace || new Namespace(); + + self._actions.forEach(function (action) { + if (action.dest !== $$.SUPPRESS) { + if (!_.has(namespace, action.dest)) { + if (action.defaultValue !== $$.SUPPRESS) { + var defaultValue = action.defaultValue; + if (_.isString(action.defaultValue)) { + defaultValue = self._getValue(action, defaultValue); + } + namespace[action.dest] = defaultValue; + } + } + } + }); + + _.keys(self._defaults).forEach(function (dest) { + namespace[dest] = self._defaults[dest]; + }); + + // parse the arguments and exit if there are any errors + try { + var res = this._parseKnownArgs(args, namespace); + + namespace = res[0]; + args = res[1]; + if (_.has(namespace, $$._UNRECOGNIZED_ARGS_ATTR)) { + args = _.union(args, namespace[$$._UNRECOGNIZED_ARGS_ATTR]); + delete namespace[$$._UNRECOGNIZED_ARGS_ATTR]; + } + return [namespace, args]; + } catch (e) { + this.error(e); + } +}; + +ArgumentParser.prototype._parseKnownArgs = function (argStrings, namespace) { + var self = this; + + var extras = []; + + // replace arg strings that are file references + if (this.fromfilePrefixChars !== null) { + argStrings = this._readArgsFromFiles(argStrings); + } + // map all mutually exclusive arguments to the other arguments + // they can't occur with + // Python has 'conflicts = action_conflicts.setdefault(mutex_action, [])' + // though I can't conceive of a way in which an action could be a member + // of two different mutually exclusive groups. + + function actionHash(action) { + // some sort of hashable key for this action + // action itself cannot be a key in actionConflicts + // I think getName() (join of optionStrings) is unique enough + return action.getName(); + } + var conflicts, key; + var actionConflicts = {}; + this._mutuallyExclusiveGroups.forEach(function (mutexGroup) { + mutexGroup._groupActions.forEach(function (mutexAction, i, groupActions) { + key = actionHash(mutexAction); + if (!_.has(actionConflicts, key)) { + actionConflicts[key] = []; + } + conflicts = actionConflicts[key]; + conflicts.push.apply(conflicts, groupActions.slice(0, i)); + conflicts.push.apply(conflicts, groupActions.slice(i + 1)); + }); + }); + + // find all option indices, and determine the arg_string_pattern + // which has an 'O' if there is an option at an index, + // an 'A' if there is an argument, or a '-' if there is a '--' + var optionStringIndices = {}; + + var argStringPatternParts = []; + + argStrings.forEach(function (argString, argStringIndex) { + if (argString === '--') { + argStringPatternParts.push('-'); + while (argStringIndex < argStrings.length) { + argStringPatternParts.push('A'); + argStringIndex++; + } + } + // otherwise, add the arg to the arg strings + // and note the index if it was an option + else { + var pattern; + var optionTuple = self._parseOptional(argString); + if (!optionTuple) { + pattern = 'A'; + } + else { + optionStringIndices[argStringIndex] = optionTuple; + pattern = 'O'; + } + argStringPatternParts.push(pattern); + } + }); + var argStringsPattern = argStringPatternParts.join(''); + + var seenActions = []; + var seenNonDefaultActions = []; + + + function takeAction(action, argumentStrings, optionString) { + seenActions.push(action); + var argumentValues = self._getValues(action, argumentStrings); + + // error if this argument is not allowed with other previously + // seen arguments, assuming that actions that use the default + // value don't really count as "present" + if (argumentValues !== action.defaultValue) { + seenNonDefaultActions.push(action); + if (!!actionConflicts[actionHash(action)]) { + actionConflicts[actionHash(action)].forEach(function (actionConflict) { + if (seenNonDefaultActions.indexOf(actionConflict) >= 0) { + throw argumentErrorHelper( + action, + format('Not allowed with argument "%s".', actionConflict.getName()) + ); + } + }); + } + } + + if (argumentValues !== $$.SUPPRESS) { + action.call(self, namespace, argumentValues, optionString); + } + } + + function consumeOptional(startIndex) { + // get the optional identified at this index + var optionTuple = optionStringIndices[startIndex]; + var action = optionTuple[0]; + var optionString = optionTuple[1]; + var explicitArg = optionTuple[2]; + + // identify additional optionals in the same arg string + // (e.g. -xyz is the same as -x -y -z if no args are required) + var actionTuples = []; + + var args, argCount, start, stop; + + while (true) { + if (!action) { + extras.push(argStrings[startIndex]); + return startIndex + 1; + } + if (!!explicitArg) { + argCount = self._matchArgument(action, 'A'); + + // if the action is a single-dash option and takes no + // arguments, try to parse more single-dash options out + // of the tail of the option string + var chars = self.prefixChars; + if (argCount === 0 && chars.indexOf(optionString[1]) < 0) { + actionTuples.push([action, [], optionString]); + optionString = optionString[0] + explicitArg[0]; + var newExplicitArg = explicitArg.slice(1) || null; + var optionalsMap = self._optionStringActions; + + if (_.keys(optionalsMap).indexOf(optionString) >= 0) { + action = optionalsMap[optionString]; + explicitArg = newExplicitArg; + } + else { + var msg = 'ignored explicit argument %r'; + throw argumentErrorHelper(action, msg); + } + } + // if the action expect exactly one argument, we've + // successfully matched the option; exit the loop + else if (argCount === 1) { + stop = startIndex + 1; + args = [explicitArg]; + actionTuples.push([action, args, optionString]); + break; + } + // error if a double-dash option did not use the + // explicit argument + else { + var message = 'ignored explicit argument %r'; + throw argumentErrorHelper(action, _.str.sprintf(message, explicitArg)); + } + } + // if there is no explicit argument, try to match the + // optional's string arguments with the following strings + // if successful, exit the loop + else { + + start = startIndex + 1; + var selectedPatterns = argStringsPattern.substr(start); + + argCount = self._matchArgument(action, selectedPatterns); + stop = start + argCount; + + + args = argStrings.slice(start, stop); + + actionTuples.push([action, args, optionString]); + break; + } + + } + + // add the Optional to the list and return the index at which + // the Optional's string args stopped + if (actionTuples.length < 1) { + throw new Error('length should be > 0'); + } + for (var i = 0; i < actionTuples.length; i++) { + takeAction.apply(self, actionTuples[i]); + } + return stop; + } + + // the list of Positionals left to be parsed; this is modified + // by consume_positionals() + var positionals = self._getPositionalActions(); + + function consumePositionals(startIndex) { + // match as many Positionals as possible + var selectedPattern = argStringsPattern.substr(startIndex); + var argCounts = self._matchArgumentsPartial(positionals, selectedPattern); + + // slice off the appropriate arg strings for each Positional + // and add the Positional and its args to the list + _.zip(positionals, argCounts).forEach(function (item) { + var action = item[0]; + var argCount = item[1]; + if (argCount === undefined) { + return; + } + var args = argStrings.slice(startIndex, startIndex + argCount); + + startIndex += argCount; + takeAction(action, args); + }); + + // slice off the Positionals that we just parsed and return the + // index at which the Positionals' string args stopped + positionals = positionals.slice(argCounts.length); + return startIndex; + } + + // consume Positionals and Optionals alternately, until we have + // passed the last option string + var startIndex = 0; + var position; + + var maxOptionStringIndex = -1; + if (!!optionStringIndices) { + for (position in optionStringIndices) { + maxOptionStringIndex = Math.max(maxOptionStringIndex, parseInt(position, 10)); + } + } + + var positionalsEndIndex, nextOptionStringIndex; + + while (startIndex <= maxOptionStringIndex) { + // consume any Positionals preceding the next option + nextOptionStringIndex = null; + for (position in optionStringIndices) { + position = parseInt(position, 10); + if (position >= startIndex) { + if (nextOptionStringIndex !== null) { + nextOptionStringIndex = Math.min(nextOptionStringIndex, position); + } + else { + nextOptionStringIndex = position; + } + } + } + + if (startIndex !== nextOptionStringIndex) { + positionalsEndIndex = consumePositionals(startIndex); + // only try to parse the next optional if we didn't consume + // the option string during the positionals parsing + if (positionalsEndIndex > startIndex) { + startIndex = positionalsEndIndex; + continue; + } + else { + startIndex = positionalsEndIndex; + } + } + + // if we consumed all the positionals we could and we're not + // at the index of an option string, there were extra arguments + if (!optionStringIndices[startIndex]) { + var strings = argStrings.slice(startIndex, nextOptionStringIndex); + extras = extras.concat(strings); + startIndex = nextOptionStringIndex; + } + // consume the next optional and any arguments for it + startIndex = consumeOptional(startIndex); + } + + // consume any positionals following the last Optional + var stopIndex = consumePositionals(startIndex); + + // if we didn't consume all the argument strings, there were extras + extras = extras.concat(_.rest(argStrings, stopIndex)); + + // if we didn't use all the Positional objects, there were too few + // arg strings supplied. + if (positionals.length > 0) { + self.error('too few arguments'); + } + + // make sure all required actions were present + self._actions.forEach(function (action) { + if (action.required) { + if (_.indexOf(seenActions, action) < 0) { + self.error(format('Argument "%s" is required', action.getName())); + } + } + }); + + // make sure all required groups have one option present + var actionUsed = false; + self._mutuallyExclusiveGroups.forEach(function (group) { + if (group.required) { + actionUsed = _.any(group._groupActions, function (action) { + return _.contains(seenNonDefaultActions, action); + }); + + // if no actions were used, report the error + if (!actionUsed) { + var names = []; + group._groupActions.forEach(function (action) { + if (action.help !== $$.SUPPRESS) { + names.push(action.getName()); + } + }); + names = names.join(' '); + var msg = 'one of the arguments ' + names + ' is required'; + self.error(msg); + } + } + }); + + // return the updated namespace and the extra arguments + return [namespace, extras]; +}; + +ArgumentParser.prototype._readArgsFromFiles = function (argStrings) { + // expand arguments referencing files + var _this = this; + var fs = require('fs'); + var newArgStrings = []; + argStrings.forEach(function (argString) { + if (_this.fromfilePrefixChars.indexOf(argString[0]) < 0) { + // for regular arguments, just add them back into the list + newArgStrings.push(argString); + } else { + // replace arguments referencing files with the file content + try { + var argstrs = []; + var filename = argString.slice(1); + var content = fs.readFileSync(filename, 'utf8'); + content = content.trim().split('\n'); + content.forEach(function (argLine) { + _this.convertArgLineToArgs(argLine).forEach(function (arg) { + argstrs.push(arg); + }); + argstrs = _this._readArgsFromFiles(argstrs); + }); + newArgStrings.push.apply(newArgStrings, argstrs); + } catch (error) { + return _this.error(error.message); + } + } + }); + return newArgStrings; +}; + +ArgumentParser.prototype.convertArgLineToArgs = function (argLine) { + return [argLine]; +}; + +ArgumentParser.prototype._matchArgument = function (action, regexpArgStrings) { + + // match the pattern for this action to the arg strings + var regexpNargs = new RegExp('^' + this._getNargsPattern(action)); + var matches = regexpArgStrings.match(regexpNargs); + var message; + + // throw an exception if we weren't able to find a match + if (!matches) { + switch (action.nargs) { + case undefined: + case null: + message = 'Expected one argument.'; + break; + case $$.OPTIONAL: + message = 'Expected at most one argument.'; + break; + case $$.ONE_OR_MORE: + message = 'Expected at least one argument.'; + break; + default: + message = 'Expected %s argument(s)'; + } + + throw argumentErrorHelper( + action, + format(message, action.nargs) + ); + } + // return the number of arguments matched + return matches[1].length; +}; + +ArgumentParser.prototype._matchArgumentsPartial = function (actions, regexpArgStrings) { + // progressively shorten the actions list by slicing off the + // final actions until we find a match + var self = this; + var result = []; + var actionSlice, pattern, matches; + var i, j; + + var getLength = function (string) { + return string.length; + }; + + for (i = actions.length; i > 0; i -= 1) { + pattern = ''; + actionSlice = actions.slice(0, i); + for (j in actionSlice) { + pattern += self._getNargsPattern(actionSlice[j]); + } + + pattern = new RegExp('^' + pattern); + matches = regexpArgStrings.match(pattern); + + if (matches && matches.length > 0) { + // need only groups + matches = matches.splice(1); + result = result.concat(matches.map(getLength)); + break; + } + } + + // return the list of arg string counts + return result; +}; + +ArgumentParser.prototype._parseOptional = function (argString) { + var action, optionString, argExplicit, optionTuples; + + // if it's an empty string, it was meant to be a positional + if (!argString) { + return null; + } + + // if it doesn't start with a prefix, it was meant to be positional + if (this.prefixChars.indexOf(argString[0]) < 0) { + return null; + } + + // if the option string is present in the parser, return the action + if (!!this._optionStringActions[argString]) { + return [this._optionStringActions[argString], argString, null]; + } + + // if it's just a single character, it was meant to be positional + if (argString.length === 1) { + return null; + } + + // if the option string before the "=" is present, return the action + if (argString.indexOf('=') >= 0) { + var argStringSplit = argString.split('='); + optionString = argStringSplit[0]; + argExplicit = argStringSplit[1]; + + if (!!this._optionStringActions[optionString]) { + action = this._optionStringActions[optionString]; + return [action, optionString, argExplicit]; + } + } + + // search through all possible prefixes of the option string + // and all actions in the parser for possible interpretations + optionTuples = this._getOptionTuples(argString); + + // if multiple actions match, the option string was ambiguous + if (optionTuples.length > 1) { + var optionStrings = optionTuples.map(function (optionTuple) { + return optionTuple[1]; + }); + this.error(format( + 'Ambiguous option: "%s" could match %s.', + argString, optionStrings.join(', ') + )); + // if exactly one action matched, this segmentation is good, + // so return the parsed action + } else if (optionTuples.length === 1) { + return optionTuples[0]; + } + + // if it was not found as an option, but it looks like a negative + // number, it was meant to be positional + // unless there are negative-number-like options + if (argString.match(this._regexpNegativeNumber)) { + if (!_.any(this._hasNegativeNumberOptionals)) { + return null; + } + } + // if it contains a space, it was meant to be a positional + if (argString.search(' ') >= 0) { + return null; + } + + // it was meant to be an optional but there is no such option + // in this parser (though it might be a valid option in a subparser) + return [null, argString, null]; +}; + +ArgumentParser.prototype._getOptionTuples = function (optionString) { + var result = []; + var chars = this.prefixChars; + var optionPrefix; + var argExplicit; + var action; + var actionOptionString; + + // option strings starting with two prefix characters are only split at + // the '=' + if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) >= 0) { + if (optionString.indexOf('=') >= 0) { + var optionStringSplit = optionString.split('=', 1); + + optionPrefix = optionStringSplit[0]; + argExplicit = optionStringSplit[1]; + } else { + optionPrefix = optionString; + argExplicit = null; + } + + for (actionOptionString in this._optionStringActions) { + if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + action = this._optionStringActions[actionOptionString]; + result.push([action, actionOptionString, argExplicit]); + } + } + + // single character options can be concatenated with their arguments + // but multiple character options always have to have their argument + // separate + } else if (chars.indexOf(optionString[0]) >= 0 && chars.indexOf(optionString[1]) < 0) { + optionPrefix = optionString; + argExplicit = null; + var optionPrefixShort = optionString.substr(0, 2); + var argExplicitShort = optionString.substr(2); + + for (actionOptionString in this._optionStringActions) { + action = this._optionStringActions[actionOptionString]; + if (actionOptionString === optionPrefixShort) { + result.push([action, actionOptionString, argExplicitShort]); + } else if (actionOptionString.substr(0, optionPrefix.length) === optionPrefix) { + result.push([action, actionOptionString, argExplicit]); + } + } + + // shouldn't ever get here + } else { + throw new Error(format('Unexpected option string: %s.', optionString)); + } + // return the collected option tuples + return result; +}; + +ArgumentParser.prototype._getNargsPattern = function (action) { + // in all examples below, we have to allow for '--' args + // which are represented as '-' in the pattern + var regexpNargs; + + switch (action.nargs) { + // the default (null) is assumed to be a single argument + case undefined: + case null: + regexpNargs = '(-*A-*)'; + break; + // allow zero or more arguments + case $$.OPTIONAL: + regexpNargs = '(-*A?-*)'; + break; + // allow zero or more arguments + case $$.ZERO_OR_MORE: + regexpNargs = '(-*[A-]*)'; + break; + // allow one or more arguments + case $$.ONE_OR_MORE: + regexpNargs = '(-*A[A-]*)'; + break; + // allow any number of options or arguments + case $$.REMAINDER: + regexpNargs = '([-AO]*)'; + break; + // allow one argument followed by any number of options or arguments + case $$.PARSER: + regexpNargs = '(-*A[-AO]*)'; + break; + // all others should be integers + default: + regexpNargs = '(-*' + _.str.repeat('-*A', action.nargs) + '-*)'; + } + + // if this is an optional action, -- is not allowed + if (action.isOptional()) { + regexpNargs = regexpNargs.replace(/-\*/g, ''); + regexpNargs = regexpNargs.replace(/-/g, ''); + } + + // return the pattern + return regexpNargs; +}; + +// +// Value conversion methods +// + +ArgumentParser.prototype._getValues = function (action, argStrings) { + var self = this; + + // for everything but PARSER args, strip out '--' + if (action.nargs !== $$.PARSER && action.nargs !== $$.REMAINDER) { + argStrings = argStrings.filter(function (arrayElement) { + return arrayElement !== '--'; + }); + } + + var value, argString; + + // optional argument produces a default when not present + if (argStrings.length === 0 && action.nargs === $$.OPTIONAL) { + + value = (action.isOptional()) ? action.constant: action.defaultValue; + + if (typeof(value) === 'string') { + value = this._getValue(action, value); + this._checkValue(action, value); + } + + // when nargs='*' on a positional, if there were no command-line + // args, use the default if it is anything other than None + } else if (argStrings.length === 0 && action.nargs === $$.ZERO_OR_MORE && + action.optionStrings.length === 0) { + + value = (action.defaultValue || argStrings); + this._checkValue(action, value); + + // single argument or optional argument produces a single value + } else if (argStrings.length === 1 && + (!action.nargs || action.nargs === $$.OPTIONAL)) { + + argString = argStrings[0]; + value = this._getValue(action, argString); + this._checkValue(action, value); + + // REMAINDER arguments convert all values, checking none + } else if (action.nargs === $$.REMAINDER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + + // PARSER arguments convert all values, but check only the first + } else if (action.nargs === $$.PARSER) { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + this._checkValue(action, value[0]); + + // all other types of nargs produce a list + } else { + value = argStrings.map(function (v) { + return self._getValue(action, v); + }); + value.forEach(function (v) { + self._checkValue(action, v); + }); + } + + // return the converted value + return value; +}; + +ArgumentParser.prototype._getValue = function (action, argString) { + var result; + + var typeFunction = this._registryGet('type', action.type, action.type); + if (!_.isFunction(typeFunction)) { + var message = format('%s is not callable', typeFunction); + throw argumentErrorHelper(action, message); + } + + // convert the value to the appropriate type + try { + result = typeFunction(argString); + + // ArgumentTypeErrors indicate errors + // If action.type is not a registered string, it is a function + // Try to deduce its name for inclusion in the error message + // Failing that, include the error message it raised. + } catch (e) { + var name = null; + if (_.isString(action.type)) { + name = action.type; + } else { + name = action.type.name || action.type.displayName || ''; + } + var msg = format('Invalid %s value: %s', name, argString); + if (name === '') {msg += '\n' + e.message; } + throw argumentErrorHelper(action, msg); + } + // return the converted value + return result; +}; + +ArgumentParser.prototype._checkValue = function (action, value) { + // converted value must be one of the choices (if specified) + var choices = action.choices; + if (!!choices) { + // choise for argument can by array or string + if ((_.isString(choices) || _.isArray(choices)) && + choices.indexOf(value) !== -1) { + return; + } + // choise for subparsers can by only hash + if (_.isObject(choices) && !_.isArray(choices) && choices[value]) { + return; + } + + if (_.isString(choices)) { + choices = choices.split('').join(', '); + } + else if (_.isArray(choices)) { + choices = choices.join(', '); + } + else { + choices = _.keys(choices).join(', '); + } + var message = format('Invalid choice: %s (choose from [%s])', value, choices); + throw argumentErrorHelper(action, message); + } +}; + +// +// Help formatting methods +// + +/** + * ArgumentParser#formatUsage -> string + * + * Return usage string + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatUsage = function () { + var formatter = this._getFormatter(); + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + return formatter.formatHelp(); +}; + +/** + * ArgumentParser#formatHelp -> string + * + * Return help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.formatHelp = function () { + var formatter = this._getFormatter(); + + // usage + formatter.addUsage(this.usage, this._actions, this._mutuallyExclusiveGroups); + + // description + formatter.addText(this.description); + + // positionals, optionals and user-defined groups + this._actionGroups.forEach(function (actionGroup) { + formatter.startSection(actionGroup.title); + formatter.addText(actionGroup.description); + formatter.addArguments(actionGroup._groupActions); + formatter.endSection(); + }); + + // epilog + formatter.addText(this.epilog); + + // determine help from format above + return formatter.formatHelp(); +}; + +ArgumentParser.prototype._getFormatter = function () { + var FormatterClass = this.formatterClass; + var formatter = new FormatterClass({prog: this.prog}); + return formatter; +}; + +// +// Print functions +// + +/** + * ArgumentParser#printUsage() -> Void + * + * Print usage + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printUsage = function () { + this._printMessage(this.formatUsage()); +}; + +/** + * ArgumentParser#printHelp() -> Void + * + * Print help + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#printing-help + **/ +ArgumentParser.prototype.printHelp = function () { + this._printMessage(this.formatHelp()); +}; + +ArgumentParser.prototype._printMessage = function (message, stream) { + if (!stream) { + stream = process.stdout; + } + if (message) { + stream.write('' + message); + } +}; + +// +// Exit functions +// + +/** + * ArgumentParser#exit(status=0, message) -> Void + * - status (int): exit status + * - message (string): message + * + * Print message in stderr/stdout and exit program + **/ +ArgumentParser.prototype.exit = function (status, message) { + if (!!message) { + if (status === 0) { + this._printMessage(message); + } + else { + this._printMessage(message, process.stderr); + } + } + + process.exit(status); +}; + +/** + * ArgumentParser#error(message) -> Void + * - err (Error|string): message + * + * Error method Prints a usage message incorporating the message to stderr and + * exits. If you override this in a subclass, + * it should not return -- it should + * either exit or throw an exception. + * + **/ +ArgumentParser.prototype.error = function (err) { + var message; + if (err instanceof Error) { + if (this.debug === true) { + throw err; + } + message = err.message; + } + else { + message = err; + } + var msg = format('%s: error: %s', this.prog, message) + $$.EOL; + + if (this.debug === true) { + throw new Error(msg); + } + + this.printUsage(process.stderr); + + return this.exit(2, msg); +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/const.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/const.js new file mode 100644 index 000000000..de831ba4e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/const.js @@ -0,0 +1,18 @@ +// +// Constants +// +module.exports.EOL = '\n'; + +module.exports.SUPPRESS = '==SUPPRESS=='; + +module.exports.OPTIONAL = '?'; + +module.exports.ZERO_OR_MORE = '*'; + +module.exports.ONE_OR_MORE = '+'; + +module.exports.PARSER = 'A...'; + +module.exports.REMAINDER = '...'; + +module.exports._UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/added_formatters.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/added_formatters.js new file mode 100644 index 000000000..cd2f369b6 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/added_formatters.js @@ -0,0 +1,88 @@ +'use strict'; + +var util = require('util'); +var _ = require('underscore'); +_.str = require('underscore.string'); + +// Constants +var $$ = require('../const'); + +var HelpFormatter = require('./formatter.js'); + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which adds default values to argument help. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +var ArgumentDefaultsHelpFormatter = function ArgumentDefaultsHelpFormatter(options) { + HelpFormatter.call(this, options); +}; + +util.inherits(ArgumentDefaultsHelpFormatter, HelpFormatter); + +ArgumentDefaultsHelpFormatter.prototype._getHelpString = function (action) { + var help = action.help; + if (action.help.indexOf('%(defaultValue)s') === -1) { + if (action.defaultValue !== $$.SUPPRESS) { + var defaulting_nargs = [$$.OPTIONAL, $$.ZERO_OR_MORE]; + if (action.isOptional() || (defaulting_nargs.indexOf(action.nargs) >= 0)) { + help += ' (default: %(defaultValue)s)'; + } + } + } + return help; +}; + +module.exports.ArgumentDefaultsHelpFormatter = ArgumentDefaultsHelpFormatter; + +/** + * new RawDescriptionHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...}) + * + * Help message formatter which retains any formatting in descriptions. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +var RawDescriptionHelpFormatter = function RawDescriptionHelpFormatter(options) { + HelpFormatter.call(this, options); +}; + +util.inherits(RawDescriptionHelpFormatter, HelpFormatter); + +RawDescriptionHelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = text.split('\n'); + lines = lines.map(function (line) { + return _.str.rtrim(indent + line); + }); + return lines.join('\n'); +}; +module.exports.RawDescriptionHelpFormatter = RawDescriptionHelpFormatter; + +/** + * new RawTextHelpFormatter(options) + * new ArgumentParser({formatterClass: argparse.RawTextHelpFormatter, ...}) + * + * Help message formatter which retains formatting of all help text. + * + * Only the name of this class is considered a public API. All the methods + * provided by the class are considered an implementation detail. + **/ + +var RawTextHelpFormatter = function RawTextHelpFormatter(options) { + RawDescriptionHelpFormatter.call(this, options); +}; + +util.inherits(RawTextHelpFormatter, RawDescriptionHelpFormatter); + +RawTextHelpFormatter.prototype._splitLines = function (text) { + return text.split('\n'); +}; + +module.exports.RawTextHelpFormatter = RawTextHelpFormatter; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/formatter.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/formatter.js new file mode 100644 index 000000000..541d918b6 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/help/formatter.js @@ -0,0 +1,803 @@ +/** + * class HelpFormatter + * + * Formatter for generating usage messages and argument help strings. Only the + * name of this class is considered a public API. All the methods provided by + * the class are considered an implementation detail. + * + * Do not call in your code, use this class only for inherits your own forvatter + * + * ToDo add [additonal formatters][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#formatter-class + **/ +'use strict'; + +var _ = require('underscore'); +_.str = require('underscore.string'); + +// Constants +var $$ = require('../const'); + + +/*:nodoc:* internal + * new Support(parent, heding) + * - parent (object): parent section + * - heading (string): header string + * + **/ +function Section(parent, heading) { + this._parent = parent; + this._heading = heading; + this._items = []; +} + +/*:nodoc:* internal + * Section#addItem(callback) -> Void + * - callback (array): tuple with function and args + * + * Add function for single element + **/ +Section.prototype.addItem = function (callback) { + this._items.push(callback); +}; + +/*:nodoc:* internal + * Section#formatHelp(formatter) -> string + * - formatter (HelpFormatter): current formatter + * + * Form help section string + * + **/ +Section.prototype.formatHelp = function (formatter) { + var itemHelp, heading; + + // format the indented section + if (!!this._parent) { + formatter._indent(); + } + + itemHelp = this._items.map(function (item) { + var obj, func, args; + + obj = formatter; + func = item[0]; + args = item[1]; + return func.apply(obj, args); + }); + itemHelp = formatter._joinParts(itemHelp); + + if (!!this._parent) { + formatter._dedent(); + } + + // return nothing if the section was empty + if (!itemHelp) { + return ''; + } + + // add the heading if the section was non-empty + heading = ''; + if (!!this._heading && this._heading !== $$.SUPPRESS) { + var currentIndent = formatter.currentIndent; + heading = _.str.repeat(' ', currentIndent) + this._heading + ':' + $$.EOL; + } + + // join the section-initialize newline, the heading and the help + return formatter._joinParts([$$.EOL, heading, itemHelp, $$.EOL]); +}; + +/** + * new HelpFormatter(options) + * + * #### Options: + * - `prog`: program name + * - `indentIncriment`: indent step, default value 2 + * - `maxHelpPosition`: max help position, default value = 24 + * - `width`: line width + * + **/ +var HelpFormatter = module.exports = function HelpFormatter(options) { + options = options || {}; + + this._prog = options.prog; + + this._maxHelpPosition = options.maxHelpPosition || 24; + this._width = (options.width || ((process.env.COLUMNS || 80) - 2)); + + this._currentIndent = 0; + this._indentIncriment = options.indentIncriment || 2; + this._level = 0; + this._actionMaxLength = 0; + + this._rootSection = new Section(null); + this._currentSection = this._rootSection; + + this._whitespaceMatcher = new RegExp('\\s+', 'g'); + this._longBreakMatcher = new RegExp($$.EOL + $$.EOL + $$.EOL + '+', 'g'); +}; + +HelpFormatter.prototype._indent = function () { + this._currentIndent += this._indentIncriment; + this._level += 1; +}; + +HelpFormatter.prototype._dedent = function () { + this._currentIndent -= this._indentIncriment; + this._level -= 1; + if (this._currentIndent < 0) { + throw new Error('Indent decreased below 0.'); + } +}; + +HelpFormatter.prototype._addItem = function (func, args) { + this._currentSection.addItem([func, args]); +}; + +// +// Message building methods +// + +/** + * HelpFormatter#startSection(heading) -> Void + * - heading (string): header string + * + * Start new help section + * + * See alse [code example][1] + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.startSection = function (heading) { + this._indent(); + var section = new Section(this._currentSection, heading); + var func = section.formatHelp.bind(section); + this._addItem(func, [this]); + this._currentSection = section; +}; + +/** + * HelpFormatter#endSection -> Void + * + * End help section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + **/ +HelpFormatter.prototype.endSection = function () { + this._currentSection = this._currentSection._parent; + this._dedent(); +}; + +/** + * HelpFormatter#addText(text) -> Void + * - text (string): plain text + * + * Add plain text into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addText = function (text) { + if (!!text && text !== $$.SUPPRESS) { + this._addItem(this._formatText, [text]); + } +}; + +/** + * HelpFormatter#addUsage(usage, actions, groups, prefix) -> Void + * - usage (string): usage text + * - actions (array): actions list + * - groups (array): groups list + * - prefix (string): usage prefix + * + * Add usage data into current section + * + * ##### Example + * + * formatter.addUsage(this.usage, this._actions, []); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.addUsage = function (usage, actions, groups, prefix) { + if (usage !== $$.SUPPRESS) { + this._addItem(this._formatUsage, [usage, actions, groups, prefix]); + } +}; + +/** + * HelpFormatter#addArgument(action) -> Void + * - action (object): action + * + * Add argument into current section + * + * Single variant of [[HelpFormatter#addArguments]] + **/ +HelpFormatter.prototype.addArgument = function (action) { + if (action.help !== $$.SUPPRESS) { + var self = this; + + // find all invocations + var invocations = [this._formatActionInvocation(action)]; + var invocationLength = invocations[0].length; + + var actionLength; + + if (!!action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + + var invocationNew = self._formatActionInvocation(subaction); + invocations.push(invocationNew); + invocationLength = Math.max(invocationLength, invocationNew.length); + + }); + this._dedent(); + } + + // update the maximum item length + actionLength = invocationLength + this._currentIndent; + this._actionMaxLength = Math.max(this._actionMaxLength, actionLength); + + // add the item to the list + this._addItem(this._formatAction, [action]); + } +}; + +/** + * HelpFormatter#addArguments(actions) -> Void + * - actions (array): actions list + * + * Mass add arguments into current section + * + * ##### Example + * + * formatter.startSection(actionGroup.title); + * formatter.addText(actionGroup.description); + * formatter.addArguments(actionGroup._groupActions); + * formatter.endSection(); + * + **/ +HelpFormatter.prototype.addArguments = function (actions) { + var self = this; + actions.forEach(function (action) { + self.addArgument(action); + }); +}; + +// +// Help-formatting methods +// + +/** + * HelpFormatter#formatHelp -> string + * + * Format help + * + * ##### Example + * + * formatter.addText(this.epilog); + * return formatter.formatHelp(); + * + **/ +HelpFormatter.prototype.formatHelp = function () { + var help = this._rootSection.formatHelp(this); + if (help) { + help = help.replace(this._longBreakMatcher, $$.EOL + $$.EOL); + help = _.str.strip(help, $$.EOL) + $$.EOL; + } + return help; +}; + +HelpFormatter.prototype._joinParts = function (partStrings) { + return partStrings.filter(function (part) { + return (!!part && part !== $$.SUPPRESS); + }).join(''); +}; + +HelpFormatter.prototype._formatUsage = function (usage, actions, groups, prefix) { + if (!prefix && !_.isString(prefix)) { + prefix = 'usage: '; + } + + actions = actions || []; + groups = groups || []; + + + // if usage is specified, use that + if (usage) { + usage = _.str.sprintf(usage, {prog: this._prog}); + + // if no optionals or positionals are available, usage is just prog + } else if (!usage && actions.length === 0) { + usage = this._prog; + + // if optionals and positionals are available, calculate usage + } else if (!usage) { + var prog = this._prog; + var optionals = []; + var positionals = []; + var actionUsage; + var textWidth; + + // split optionals from positionals + actions.forEach(function (action) { + if (action.isOptional()) { + optionals.push(action); + } else { + positionals.push(action); + } + }); + + // build full usage string + actionUsage = this._formatActionsUsage([].concat(optionals, positionals), groups); + usage = [prog, actionUsage].join(' '); + + // wrap the usage parts if it's too long + textWidth = this._width - this._currentIndent; + if ((prefix.length + usage.length) > textWidth) { + + // break usage into wrappable parts + var regexpPart = new RegExp('\\(.*?\\)+|\\[.*?\\]+|\\S+', 'g'); + var optionalUsage = this._formatActionsUsage(optionals, groups); + var positionalUsage = this._formatActionsUsage(positionals, groups); + + + var optionalParts = optionalUsage.match(regexpPart); + var positionalParts = positionalUsage.match(regexpPart) || []; + + if (optionalParts.join(' ') !== optionalUsage) { + throw new Error('assert "optionalParts.join(\' \') === optionalUsage"'); + } + if (positionalParts.join(' ') !== positionalUsage) { + throw new Error('assert "positionalParts.join(\' \') === positionalUsage"'); + } + + // helper for wrapping lines + var _getLines = function (parts, indent, prefix) { + var lines = []; + var line = []; + + var lineLength = !!prefix ? prefix.length - 1: indent.length - 1; + + parts.forEach(function (part) { + if (lineLength + 1 + part.length > textWidth) { + lines.push(indent + line.join(' ')); + line = []; + lineLength = indent.length - 1; + } + line.push(part); + lineLength += part.length + 1; + }); + + if (line) { + lines.push(indent + line.join(' ')); + } + if (prefix) { + lines[0] = lines[0].substr(indent.length); + } + return lines; + }; + + var lines, indent, parts; + // if prog is short, follow it with optionals or positionals + if (prefix.length + prog.length <= 0.75 * textWidth) { + indent = _.str.repeat(' ', (prefix.length + prog.length + 1)); + if (optionalParts) { + lines = [].concat( + _getLines([prog].concat(optionalParts), indent, prefix), + _getLines(positionalParts, indent) + ); + } else if (positionalParts) { + lines = _getLines([prog].concat(positionalParts), indent, prefix); + } else { + lines = [prog]; + } + + // if prog is long, put it on its own line + } else { + indent = _.str.repeat(' ', prefix.length); + parts = optionalParts + positionalParts; + lines = _getLines(parts, indent); + if (lines.length > 1) { + lines = [].concat( + _getLines(optionalParts, indent), + _getLines(positionalParts, indent) + ); + } + lines = [prog] + lines; + } + // join lines into usage + usage = lines.join($$.EOL); + } + } + + // prefix with 'usage:' + return prefix + usage + $$.EOL + $$.EOL; +}; + +HelpFormatter.prototype._formatActionsUsage = function (actions, groups) { + // find group indices and identify actions in groups + var groupActions = []; + var inserts = []; + var self = this; + + groups.forEach(function (group) { + var end; + var i; + + var start = actions.indexOf(group._groupActions[0]); + if (start >= 0) { + end = start + group._groupActions.length; + + //if (actions.slice(start, end) === group._groupActions) { + if (_.isEqual(actions.slice(start, end), group._groupActions)) { + group._groupActions.forEach(function (action) { + groupActions.push(action); + }); + + if (!group.required) { + if (!!inserts[start]) { + inserts[start] += ' ['; + } + else { + inserts[start] = '['; + } + inserts[end] = ']'; + } else { + if (!!inserts[start]) { + inserts[start] += ' ('; + } + else { + inserts[start] = '('; + } + inserts[end] = ')'; + } + for (i = start + 1; i < end; i += 1) { + inserts[i] = '|'; + } + } + } + }); + + // collect all actions format strings + var parts = []; + + actions.forEach(function (action, actionIndex) { + var part; + var optionString; + var argsDefault; + var argsString; + + // suppressed arguments are marked with None + // remove | separators for suppressed arguments + if (action.help === $$.SUPPRESS) { + parts.push(null); + if (inserts[actionIndex] === '|') { + inserts.splice(actionIndex, actionIndex); + } else if (inserts[actionIndex + 1] === '|') { + inserts.splice(actionIndex + 1, actionIndex + 1); + } + + // produce all arg strings + } else if (!action.isOptional()) { + part = self._formatArgs(action, action.dest); + + // if it's in a group, strip the outer [] + if (groupActions.indexOf(action) >= 0) { + if (part[0] === '[' && part[part.length - 1] === ']') { + part = part.slice(1, -1); + } + } + // add the action string to the list + parts.push(part); + + // produce the first way to invoke the option in brackets + } else { + optionString = action.optionStrings[0]; + + // if the Optional doesn't take a value, format is: -s or --long + if (action.nargs === 0) { + part = '' + optionString; + + // if the Optional takes a value, format is: -s ARGS or --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = self._formatArgs(action, argsDefault); + part = optionString + ' ' + argsString; + } + // make it look optional if it's not required or in a group + if (!action.required && groupActions.indexOf(action) < 0) { + part = '[' + part + ']'; + } + // add the action string to the list + parts.push(part); + } + }); + + // insert things at the necessary indices + for (var i = inserts.length - 1; i >= 0; --i) { + if (inserts[i] !== null) { + parts.splice(i, 0, inserts[i]); + } + } + + // join all the action items with spaces + var text = parts.filter(function (part) { + return !!part; + }).join(' '); + + // clean up separators for mutually exclusive groups + text = text.replace(/([\[(]) /g, '$1'); // remove spaces + text = text.replace(/ ([\])])/g, '$1'); + text = text.replace(/\[ *\]/g, ''); // remove empty groups + text = text.replace(/\( *\)/g, ''); + text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups + + text = _.str.strip(text); + + // return the text + return text; +}; + +HelpFormatter.prototype._formatText = function (text) { + text = _.str.sprintf(text, {prog: this._prog}); + var textWidth = this._width - this._currentIndent; + var indentIncriment = _.str.repeat(' ', this._currentIndent); + return this._fillText(text, textWidth, indentIncriment) + $$.EOL + $$.EOL; +}; + +HelpFormatter.prototype._formatAction = function (action) { + var self = this; + + var helpText; + var helpLines; + var parts; + var indentFirst; + + // determine the required width and the entry label + var helpPosition = Math.min(this._actionMaxLength + 2, this._maxHelpPosition); + var helpWidth = this._width - helpPosition; + var actionWidth = helpPosition - this._currentIndent - 2; + var actionHeader = this._formatActionInvocation(action); + + // no help; start on same line and add a final newline + if (!action.help) { + actionHeader = _.str.repeat(' ', this._currentIndent) + actionHeader + $$.EOL; + + // short action name; start on the same line and pad two spaces + } else if (actionHeader.length <= actionWidth) { + actionHeader = _.str.repeat(' ', this._currentIndent) + + actionHeader + + ' ' + + _.str.repeat(' ', actionWidth - actionHeader.length); + indentFirst = 0; + + // long action name; start on the next line + } else { + actionHeader = _.str.repeat(' ', this._currentIndent) + actionHeader + $$.EOL; + indentFirst = helpPosition; + } + + // collect the pieces of the action help + parts = [actionHeader]; + + // if there was help for the action, add lines of help text + if (!!action.help) { + helpText = this._expandHelp(action); + helpLines = this._splitLines(helpText, helpWidth); + parts.push(_.str.repeat(' ', indentFirst) + helpLines[0] + $$.EOL); + helpLines.slice(1).forEach(function (line) { + parts.push(_.str.repeat(' ', helpPosition) + line + $$.EOL); + }); + + // or add a newline if the description doesn't end with one + } else if (actionHeader.charAt(actionHeader.length - 1) !== $$.EOL) { + parts.push($$.EOL); + } + // if there are any sub-actions, add their help as well + if (!!action._getSubactions) { + this._indent(); + action._getSubactions().forEach(function (subaction) { + parts.push(self._formatAction(subaction)); + }); + this._dedent(); + } + // return a single string + return this._joinParts(parts); +}; + +HelpFormatter.prototype._formatActionInvocation = function (action) { + if (!action.isOptional()) { + var format_func = this._metavarFormatter(action, action.dest); + var metavars = format_func(1); + return metavars[0]; + } else { + var parts = []; + var argsDefault; + var argsString; + + // if the Optional doesn't take a value, format is: -s, --long + if (action.nargs === 0) { + parts = parts.concat(action.optionStrings); + + // if the Optional takes a value, format is: -s ARGS, --long ARGS + } else { + argsDefault = action.dest.toUpperCase(); + argsString = this._formatArgs(action, argsDefault); + action.optionStrings.forEach(function (optionString) { + parts.push(optionString + ' ' + argsString); + }); + } + return parts.join(', '); + } +}; + +HelpFormatter.prototype._metavarFormatter = function (action, metavarDefault) { + var result; + + if (!!action.metavar || action.metavar === '') { + result = action.metavar; + } else if (!!action.choices) { + var choices = action.choices; + + if (_.isString(choices)) { + choices = choices.split('').join(', '); + } else if (_.isArray(choices)) { + choices = choices.join(','); + } + else + { + choices = _.keys(choices).join(','); + } + result = '{' + choices + '}'; + } else { + result = metavarDefault; + } + + return function (size) { + if (Array.isArray(result)) { + return result; + } else { + var metavars = []; + for (var i = 0; i < size; i += 1) { + metavars.push(result); + } + return metavars; + } + }; +}; + +HelpFormatter.prototype._formatArgs = function (action, metavarDefault) { + var result; + var metavars; + + var buildMetavar = this._metavarFormatter(action, metavarDefault); + + switch (action.nargs) { + case undefined: + case null: + metavars = buildMetavar(1); + result = '' + metavars[0]; + break; + case $$.OPTIONAL: + metavars = buildMetavar(1); + result = '[' + metavars[0] + ']'; + break; + case $$.ZERO_OR_MORE: + metavars = buildMetavar(2); + result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]'; + break; + case $$.ONE_OR_MORE: + metavars = buildMetavar(2); + result = '' + metavars[0] + ' [' + metavars[1] + ' ...]'; + break; + case $$.REMAINDER: + result = '...'; + break; + case $$.PARSER: + metavars = buildMetavar(1); + result = metavars[0] + ' ...'; + break; + default: + metavars = buildMetavar(action.nargs); + result = metavars.join(' '); + } + return result; +}; + +HelpFormatter.prototype._expandHelp = function (action) { + var actionProperty; + var actionValue; + + var params = {prog: this._prog}; + + for (actionProperty in action) { + if (action.hasOwnProperty(actionProperty)) { + actionValue = action[actionProperty]; + + if (actionValue !== $$.SUPPRESS) { + params[actionProperty] = actionValue; + } + } + } + + if (!!params.choices) { + if (_.isString(params.choices)) { + params.choices = params.choices.split('').join(', '); + } + else if (_.isArray(params.choices)) { + params.choices = params.choices.join(', '); + } + else { + params.choices = _.keys(params.choices).join(', '); + } + } + + return _.str.sprintf(this._getHelpString(action), params); +}; + +HelpFormatter.prototype._splitLines = function (text, width) { + var lines = []; + var delimiters = [" ", ".", ",", "!", "?"]; + var re = new RegExp('[' + delimiters.join('') + '][^' + delimiters.join('') + ']*$'); + + text = text.replace(/[\n\|\t]/g, ' '); + + text = _.str.strip(text); + text = text.replace(this._whitespaceMatcher, ' '); + + // Wraps the single paragraph in text (a string) so every line + // is at most width characters long. + text.split($$.EOL).forEach(function (line) { + if (width >= line.length) { + lines.push(line); + return; + } + + var wrapStart = 0; + var wrapEnd = width; + var delimiterIndex = 0; + while (wrapEnd <= line.length) { + if (wrapEnd !== line.length && delimiters.indexOf(line[wrapEnd] < -1)) { + delimiterIndex = (re.exec(line.substring(wrapStart, wrapEnd)) || {}).index; + wrapEnd = wrapStart + delimiterIndex + 1; + } + lines.push(line.substring(wrapStart, wrapEnd)); + wrapStart = wrapEnd; + wrapEnd += width; + } + if (wrapStart < line.length) { + lines.push(line.substring(wrapStart, wrapEnd)); + } + }); + + return lines; +}; + +HelpFormatter.prototype._fillText = function (text, width, indent) { + var lines = this._splitLines(text, width); + lines = lines.map(function (line) { + return indent + line; + }); + return lines.join($$.EOL); +}; + +HelpFormatter.prototype._getHelpString = function (action) { + return action.help; +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/namespace.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/namespace.js new file mode 100644 index 000000000..3546f2daf --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/lib/namespace.js @@ -0,0 +1,77 @@ +/** + * class Namespace + * + * Simple object for storing attributes. Implements equality by attribute names + * and values, and provides a simple string representation. + * + * See also [original guide][1] + * + * [1]:http://docs.python.org/dev/library/argparse.html#the-namespace-object + **/ +'use strict'; + +var _ = require('underscore'); + +/** + * new Namespace(options) + * - options(object): predefined propertis for result object + * + **/ +var Namespace = module.exports = function Namespace(options) { + _.extend(this, options); +}; + +/** + * Namespace#isset(key) -> Boolean + * - key (string|number): property name + * + * Tells whenever `namespace` contains given `key` or not. + **/ +Namespace.prototype.isset = function (key) { + return _.has(this, key); +}; + +/** + * Namespace#set(key, value) -> self + * -key (string|number|object): propery name + * -value (mixed): new property value + * + * Set the property named key with value. + * If key object then set all key properties to namespace object + **/ +Namespace.prototype.set = function (key, value) { + if (typeof (key) === 'object') { + _.extend(this, key); + } else { + this[key] = value; + } + return this; +}; + +/** + * Namespace#get(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return the property key or defaulValue if not set + **/ +Namespace.prototype.get = function (key, defaultValue) { + return !this[key] ? defaultValue: this[key]; +}; + +/** + * Namespace#unset(key, defaultValue) -> mixed + * - key (string|number): property name + * - defaultValue (mixed): default value + * + * Return data[key](and delete it) or defaultValue + **/ +Namespace.prototype.unset = function (key, defaultValue) { + var value = this[key]; + if (value !== null) { + delete this[key]; + return value; + } else { + return defaultValue; + } +}; diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/.travis.yml b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/.travis.yml new file mode 100644 index 000000000..ab27b29b7 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/.travis.yml @@ -0,0 +1,8 @@ +language: ruby +rvm: + - 1.9.3 + +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sleep 2 \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile new file mode 100644 index 000000000..aed29c3ca --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem 'uglifier' +gem 'rake' diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile.lock b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile.lock new file mode 100644 index 000000000..2c52be466 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Gemfile.lock @@ -0,0 +1,17 @@ +GEM + remote: https://rubygems.org/ + specs: + execjs (1.4.0) + multi_json (~> 1.0) + multi_json (1.3.6) + rake (0.9.2.2) + uglifier (1.3.0) + execjs (>= 0.3.0) + multi_json (~> 1.0, >= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + rake + uglifier diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/README.markdown b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/README.markdown new file mode 100644 index 000000000..1a39ad965 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/README.markdown @@ -0,0 +1,814 @@ +# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) # + + + +Javascript lacks complete string manipulation operations. +This an attempt to fill that gap. List of build-in methods can be found +for example from [Dive Into JavaScript][d]. + +[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object + + +As name states this an extension for [Underscore.js][u], but it can be used +independently from **_s**-global variable. But with Underscore.js you can +use Object-Oriented style and chaining: + +[u]: http://documentcloud.github.com/underscore/ + +```javascript +_(" epeli ").chain().trim().capitalize().value() +=> "Epeli" +``` + +## Download ## + + * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb* + * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb* + + +## Node.js installation ## + +**npm package** + + npm install underscore.string + +**Standalone usage**: + +```javascript +var _s = require('underscore.string'); +``` + +**Integrate with Underscore.js**: + +```javascript +var _ = require('underscore'); + +// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains) +_.str = require('underscore.string'); + +// Mix in non-conflict functions to Underscore namespace if you want +_.mixin(_.str.exports()); + +// All functions, include conflict, will be available through _.str object +_.str.include('Underscore.string', 'string'); // => true +``` + +**Or Integrate with Underscore.js without module loading** + +Run the following expression after Underscore.js and Underscore.string are loaded +```javascript +// _.str becomes a global variable if no module loading is detected +// Mix in non-conflict functions to Underscore namespace +_.mixin(_.str.exports()); +``` + +## String Functions ## + +For availability of functions in this way you need to mix in Underscore.string functions: + +```javascript +_.mixin(_.string.exports()); +``` + +otherwise functions from examples will be available through _.string or _.str objects: + +```javascript +_.str.capitalize('epeli') +=> "Epeli" +``` + +**numberFormat** _.numberFormat(number, [ decimals=0, decimalSeparator='.', orderSeparator=',']) + +Formats the numbers. + +```javascript +_.numberFormat(1000, 2) +=> "1,000.00" + +_.numberFormat(123456789.123, 5, '.', ',') +=> "123,456,789.12300" +``` + + +**levenshtein** _.levenshtein(string1, string2) + +Calculates [Levenshtein distance][ld] between two strings. +[ld]: http://en.wikipedia.org/wiki/Levenshtein_distance + +```javascript +_.levenshtein('kitten', 'kittah') +=> 2 +``` + +**capitalize** _.capitalize(string) + +Converts first letter of the string to uppercase. + +```javascript +_.capitalize("foo Bar") +=> "Foo Bar" +``` + +**chop** _.chop(string, step) + +```javascript +_.chop('whitespace', 3) +=> ['whi','tes','pac','e'] +``` + +**clean** _.clean(str) + +Compress some whitespaces to one. + +```javascript +_.clean(" foo bar ") +=> 'foo bar' +``` + +**chars** _.chars(str) + +```javascript +_.chars('Hello') +=> ['H','e','l','l','o'] +``` + +**swapCase** _.swapCase(str) + +Returns a copy of the string in which all the case-based characters have had their case swapped. + +```javascript +_.swapCase('hELLO') +=> 'Hello' +``` + +**include** available only through _.str object, because Underscore has function with the same name. + +```javascript +_.str.include("foobar", "ob") +=> true +``` + +(removed) **includes** _.includes(string, substring) + +Tests if string contains a substring. + +```javascript +_.includes("foobar", "ob") +=> true +``` + +**includes** function was removed + +But you can create it in this way, for compatibility with previous versions: + +```javascript +_.includes = _.str.include +``` + +**count** _.count(string, substring) + +```javascript +_('Hello world').count('l') +=> 3 +``` + +**escapeHTML** _.escapeHTML(string) + +Converts HTML special characters to their entity equivalents. + +```javascript +_('
      Blah blah blah
      ').escapeHTML(); +=> '<div>Blah blah blah</div>' +``` + +**unescapeHTML** _.unescapeHTML(string) + +Converts entity characters to HTML equivalents. + +```javascript +_('<div>Blah blah blah</div>').unescapeHTML(); +=> '
      Blah blah blah
      ' +``` + +**insert** _.insert(string, index, substing) + +```javascript +_('Hello ').insert(6, 'world') +=> 'Hello world' +``` + +**isBlank** _.isBlank(string) + +```javascript +_('').isBlank(); // => true +_('\n').isBlank(); // => true +_(' ').isBlank(); // => true +_('a').isBlank(); // => false +``` + +**join** _.join(separator, *strings) + +Joins strings together with given separator + +```javascript +_.join(" ", "foo", "bar") +=> "foo bar" +``` + +**lines** _.lines(str) + +```javascript +_.lines("Hello\nWorld") +=> ["Hello", "World"] +``` + +**reverse** available only through _.str object, because Underscore has function with the same name. + +Return reversed string: + +```javascript +_.str.reverse("foobar") +=> 'raboof' +``` + +**splice** _.splice(string, index, howmany, substring) + +Like a array splice. + +```javascript +_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli') +=> 'https://edtsech@bitbucket.org/epeli/underscore.strings' +``` + +**startsWith** _.startsWith(string, starts) + +This method checks whether string starts with starts. + +```javascript +_("image.gif").startsWith("image") +=> true +``` + +**endsWith** _.endsWith(string, ends) + +This method checks whether string ends with ends. + +```javascript +_("image.gif").endsWith("gif") +=> true +``` + +**succ** _.succ(str) + +Returns the successor to str. + +```javascript +_('a').succ() +=> 'b' + +_('A').succ() +=> 'B' +``` + +**supplant** + +Supplant function was removed, use Underscore.js [template function][p]. + +[p]: http://documentcloud.github.com/underscore/#template + +**strip** alias for *trim* + +**lstrip** alias for *ltrim* + +**rstrip** alias for *rtrim* + +**titleize** _.titleize(string) + +```javascript +_('my name is epeli').titleize() +=> 'My Name Is Epeli' +``` + +**camelize** _.camelize(string) + +Converts underscored or dasherized string to a camelized one + +```javascript +_('-moz-transform').camelize() +=> 'MozTransform' +``` + +**classify** _.classify(string) + +Converts string to camelized class name + +```javascript +_('some_class_name').classify() +=> 'SomeClassName' +``` + +**underscored** _.underscored(string) + +Converts a camelized or dasherized string into an underscored one + +```javascript +_('MozTransform').underscored() +=> 'moz_transform' +``` + +**dasherize** _.dasherize(string) + +Converts a underscored or camelized string into an dasherized one + +```javascript +_('MozTransform').dasherize() +=> '-moz-transform' +``` + +**humanize** _.humanize(string) + +Converts an underscored, camelized, or dasherized string into a humanized one. +Also removes beginning and ending whitespace, and removes the postfix '_id'. + +```javascript +_(' capitalize dash-CamelCase_underscore trim ').humanize() +=> 'Capitalize dash camel case underscore trim' +``` + +**trim** _.trim(string, [characters]) + +trims defined characters from begining and ending of the string. +Defaults to whitespace characters. + +```javascript +_.trim(" foobar ") +=> "foobar" + +_.trim("_-foobar-_", "_-") +=> "foobar" +``` + + +**ltrim** _.ltrim(string, [characters]) + +Left trim. Similar to trim, but only for left side. + + +**rtrim** _.rtrim(string, [characters]) + +Right trim. Similar to trim, but only for right side. + +**truncate** _.truncate(string, length, truncateString) + +```javascript +_('Hello world').truncate(5) +=> 'Hello...' + +_('Hello').truncate(10) +=> 'Hello' +``` + +**prune** _.prune(string, length, pruneString) + +Elegant version of truncate. +Makes sure the pruned string does not exceed the original length. +Avoid half-chopped words when truncating. + +```javascript +_('Hello, world').prune(5) +=> 'Hello...' + +_('Hello, world').prune(8) +=> 'Hello...' + +_('Hello, world').prune(5, ' (read a lot more)') +=> 'Hello, world' (as adding "(read a lot more)" would be longer than the original string) + +_('Hello, cruel world').prune(15) +=> 'Hello, cruel...' + +_('Hello').prune(10) +=> 'Hello' +``` + +**words** _.words(str, delimiter=/\s+/) + +Split string by delimiter (String or RegExp), /\s+/ by default. + +```javascript +_.words(" I love you ") +=> ["I","love","you"] + +_.words("I_love_you", "_") +=> ["I","love","you"] + +_.words("I-love-you", /-/) +=> ["I","love","you"] + +_.words(" ") +=> [] +``` + +**sprintf** _.sprintf(string format, *arguments) + +C like string formatting. +Credits goes to [Alexandru Marasteanu][o]. +For more detailed documentation, see the [original page][o]. + +[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript + +```javascript +_.sprintf("%.1f", 1.17) +"1.2" +``` + +**pad** _.pad(str, length, [padStr, type]) + +pads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`" "`). `padStr` is truncated to a single character if necessary. + +```javascript +_.pad("1", 8) +-> " 1"; + +_.pad("1", 8, '0') +-> "00000001"; + +_.pad("1", 8, '0', 'right') +-> "10000000"; + +_.pad("1", 8, '0', 'both') +-> "00001000"; + +_.pad("1", 8, 'bleepblorp', 'both') +-> "bbbb1bbb"; +``` + +**lpad** _.lpad(str, length, [padStr]) + +left-pad a string. Alias for `pad(str, length, padStr, 'left')` + +```javascript +_.lpad("1", 8, '0') +-> "00000001"; +``` + +**rpad** _.rpad(str, length, [padStr]) + +right-pad a string. Alias for `pad(str, length, padStr, 'right')` + +```javascript +_.rpad("1", 8, '0') +-> "10000000"; +``` + +**lrpad** _.lrpad(str, length, [padStr]) + +left/right-pad a string. Alias for `pad(str, length, padStr, 'both')` + +```javascript +_.lrpad("1", 8, '0') +-> "00001000"; +``` + +**center** alias for **lrpad** + +**ljust** alias for *rpad* + +**rjust** alias for *lpad* + +**toNumber** _.toNumber(string, [decimals]) + +Parse string to number. Returns NaN if string can't be parsed to number. + +```javascript +_('2.556').toNumber() +=> 3 + +_('2.556').toNumber(1) +=> 2.6 +``` + +**strRight** _.strRight(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRight('_') +=> "is_a_test_string"; +``` + +**strRightBack** _.strRightBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRightBack('_') +=> "string"; +``` + +**strLeft** _.strLeft(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeft('_') +=> "This"; +``` + +**strLeftBack** _.strLeftBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeftBack('_') +=> "This_is_a_test"; +``` + +**stripTags** + +Removes all html tags from string. + +```javascript +_('a link').stripTags() +=> 'a link' + +_('a link').stripTags() +=> 'a linkalert("hello world!")' +``` + +**toSentence** _.toSentence(array, [delimiter, lastDelimiter]) + +Join an array into a human readable sentence. + +```javascript +_.toSentence(['jQuery', 'Mootools', 'Prototype']) +=> 'jQuery, Mootools and Prototype'; + +_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ') +=> 'jQuery, Mootools unt Prototype'; +``` + +**toSentenceSerial** _.toSentenceSerial(array, [delimiter, lastDelimiter]) + +The same as `toSentence`, but adjusts delimeters to use [Serial comma](http://en.wikipedia.org/wiki/Serial_comma). + +```javascript +_.toSentenceSerial(['jQuery', 'Mootools']) +=> 'jQuery and Mootools'; + +_.toSentenceSerial(['jQuery', 'Mootools', 'Prototype']) +=> 'jQuery, Mootools, and Prototype' + +_.toSentenceSerial(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt '); +=> 'jQuery, Mootools, unt Prototype'; +``` + +**repeat** _.repeat(string, count, [separator]) + +Repeats a string count times. + +```javascript +_.repeat("foo", 3) +=> 'foofoofoo'; + +_.repeat("foo", 3, "bar") +=> 'foobarfoobarfoo' +``` + +**surround** _.surround(string, wrap) + +Surround a string with another string. + +```javascript +_.surround("foo", "ab") +=> 'abfooab'; +``` + +**quote** _.quote(string, quoteChar) or _.q(string, quoteChar) + +Quotes a string. `quoteChar` defaults to `"`. + +```javascript +_.quote('foo', quoteChar) +=> '"foo"'; +``` +**unquote** _.unquote(string, quoteChar) + +Unquotes a string. `quoteChar` defaults to `"`. + +```javascript +_.unquote('"foo"') +=> 'foo'; +_.unquote("'foo'", "'") +=> 'foo'; +``` + + +**slugify** _.slugify(string) + +Transform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash. + +```javascript +_.slugify("Un éléphant à l'orée du bois") +=> 'un-elephant-a-loree-du-bois'; +``` + +***Caution: this function is charset dependent*** + +**naturalCmp** array.sort(_.naturalCmp) + +Naturally sort strings like humans would do. + +```javascript +['foo20', 'foo5'].sort(_.naturalCmp) +=> [ 'foo5', 'foo20' ] +``` + +**toBoolean** _.toBoolean(string) or _.toBool(string) + +Turn strings that can be commonly considered as booleas to real booleans. Such as "true", "false", "1" and "0". This function is case insensitive. + +```javascript +_.toBoolean("true") +=> true +_.toBoolean("FALSE") +=> false +_.toBoolean("random") +=> undefined +``` + +It can be customized by giving arrays of truth and falsy value matcher as parameters. Matchers can be also RegExp objects. + +```javascript +_.toBoolean("truthy", ["truthy"], ["falsy"]) +=> true +_.toBoolean("true only at start", [/^true/]) +=> true +``` + +## Roadmap ## + +Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. + +#### Problems + +We lose two things for `include` and `reverse` methods from `_.string`: + +* Calls like `_('foobar').include('bar')` aren't available; +* Chaining isn't available too. + +But if you need this functionality you can create aliases for conflict functions which will be convenient for you: + +```javascript +_.mixin({ + includeString: _.str.include, + reverseString: _.str.reverse +}) + +// Now wrapper calls and chaining are available. +_('foobar').chain().reverseString().includeString('rab').value() +``` + +#### Standalone Usage + +If you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias +But of course you can just reassign `_` variable with `_.string` + +```javascript +_ = _.string +``` + +## Changelog ## + +### 2.3.3 ### + +* Add `toBoolean` +* Add `unquote` +* Add quote char option to `quote` +* Support dash-separated words in `titleize` + +### 2.3.2 ### + +* Add `naturalCmp` +* Bug fix to `camelize` +* Add ă, ș, ț and ś to `slugify` +* Doc updates +* Add support for [component](http://component.io/) +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.1...v2.3.2) + +### 2.3.1 ### + +* Bug fixes to `escapeHTML`, `classify`, `substr` +* Faster `count` +* Documentation fixes +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.0...v2.3.1) + +### 2.3.0 ### + +* Added `numberformat` method +* Added `levenshtein` method (Levenshtein distance calculation) +* Added `swapCase` method +* Changed default behavior of `words` method +* Added `toSentenceSerial` method +* Added `surround` and `quote` methods + +### 2.2.1 ### + +* Same as 2.2.0 (2.2.0rc on npm) to fix some npm drama + +### 2.2.0 ### + +* Capitalize method behavior changed +* Various perfomance tweaks + +### 2.1.1### + +* Fixed words method bug +* Added classify method + +### 2.1.0 ### + +* AMD support +* Added toSentence method +* Added slugify method +* Lots of speed optimizations + +### 2.0.0 ### + +* Added prune, humanize functions +* Added _.string (_.str) namespace for Underscore.string library +* Removed includes function + +For upgrading to this version you need to mix in Underscore.string library to Underscore object: + +```javascript +_.mixin(_.string.exports()); +``` + +and all non-conflict Underscore.string functions will be available through Underscore object. +Also function `includes` has been removed, you should replace this function by `_.str.include` +or create alias `_.includes = _.str.include` and all your code will work fine. + +### 1.1.6 ### + +* Fixed reverse and truncate +* Added isBlank, stripTags, inlude(alias for includes) +* Added uglifier compression + +### 1.1.5 ### + +* Added strRight, strRightBack, strLeft, strLeftBack + +### 1.1.4 ### + +* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust +* Integration with Underscore 1.1.6 + +### 1.1.3 ### + +* Added methods: underscored, camelize, dasherize +* Support newer version of npm + +### 1.1.2 ### + +* Created functions: lines, chars, words functions + +### 1.0.2 ### + +* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible) +* Removed 'reverse' function, because this function override underscore.js 'reverse' + +## Contribute ## + +* Fork & pull request. Don't forget about tests. +* If you planning add some feature please create issue before. + +Otherwise changes will be rejected. + +## Contributors list ## +[Can be found here](https://github.com/epeli/underscore.string/graphs/contributors). + + +## Licence ## + +The MIT License + +Copyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Rakefile b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Rakefile new file mode 100644 index 000000000..2cd9eed97 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/Rakefile @@ -0,0 +1,23 @@ +# encoding: utf-8 +task default: :test + +desc 'Use UglifyJS to compress Underscore.string' +task :build do + require 'uglifier' + source = File.read('lib/underscore.string.js', :encoding => 'utf-8') + compressed = Uglifier.compile(source, copyright: false) + File.open('dist/underscore.string.min.js', 'w'){ |f| f.write compressed } + compression_rate = compressed.length.to_f/source.length + puts "compressed dist/underscore.string.min.js: #{compressed.length}/#{source.length} #{(compression_rate * 100).round}%" +end + +desc 'Run tests' +task :test do + puts "Running underscore.string test suite." + result1 = system %{phantomjs ./test/run-qunit.js "test/test.html"} + + puts "Running Underscore test suite." + result2 = system %{phantomjs ./test/run-qunit.js "test/test_underscore/index.html"} + + exit(result1 && result2 ? 0 : 1) +end diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/component.json b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/component.json new file mode 100644 index 000000000..ae91b65b5 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/component.json @@ -0,0 +1,11 @@ +{ + "name": "underscore.string", + "repo": "epeli/underscore.string", + "description": "String manipulation extensions for Underscore.js javascript library", + "version": "2.3.3", + "keywords": ["underscore", "string"], + "dependencies": {}, + "development": {}, + "main": "lib/underscore.string.js", + "scripts": ["lib/underscore.string.js"] +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/dist/underscore.string.min.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/dist/underscore.string.min.js new file mode 100644 index 000000000..4f6b2b93e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/dist/underscore.string.min.js @@ -0,0 +1 @@ +!function(e,n){"use strict";function r(e,n){var r,t,u=e.toLowerCase();for(n=[].concat(n),r=0;n.length>r;r+=1)if(t=n[r]){if(t.test&&t.test(e))return!0;if(t.toLowerCase()===u)return!0}}var t=n.prototype.trim,u=n.prototype.trimRight,i=n.prototype.trimLeft,l=function(e){return 1*e||0},o=function(e,n){if(1>n)return"";for(var r="";n>0;)1&n&&(r+=e),n>>=1,e+=e;return r},a=[].slice,c=function(e){return null==e?"\\s":e.source?e.source:"["+g.escapeRegExp(e)+"]"},s={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},f={};for(var p in s)f[s[p]]=p;f["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var r=o,t=function(){return t.cache.hasOwnProperty(arguments[0])||(t.cache[arguments[0]]=t.parse(arguments[0])),t.format.call(null,t.cache[arguments[0]],arguments)};return t.format=function(t,u){var i,l,o,a,c,s,f,p=1,g=t.length,d="",m=[];for(l=0;g>l;l++)if(d=e(t[l]),"string"===d)m.push(t[l]);else if("array"===d){if(a=t[l],a[2])for(i=u[p],o=0;a[2].length>o;o++){if(!i.hasOwnProperty(a[2][o]))throw new Error(h('[_.sprintf] property "%s" does not exist',a[2][o]));i=i[a[2][o]]}else i=a[1]?u[a[1]]:u[p++];if(/[^s]/.test(a[8])&&"number"!=e(i))throw new Error(h("[_.sprintf] expecting number but found %s",e(i)));switch(a[8]){case"b":i=i.toString(2);break;case"c":i=n.fromCharCode(i);break;case"d":i=parseInt(i,10);break;case"e":i=a[7]?i.toExponential(a[7]):i.toExponential();break;case"f":i=a[7]?parseFloat(i).toFixed(a[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=(i=n(i))&&a[7]?i.substring(0,a[7]):i;break;case"u":i=Math.abs(i);break;case"x":i=i.toString(16);break;case"X":i=i.toString(16).toUpperCase()}i=/[def]/.test(a[8])&&a[3]&&i>=0?"+"+i:i,s=a[4]?"0"==a[4]?"0":a[4].charAt(1):" ",f=a[6]-n(i).length,c=a[6]?r(s,f):"",m.push(a[5]?i+c:c+i)}return m.join("")},t.cache={},t.parse=function(e){for(var n=e,r=[],t=[],u=0;n;){if(null!==(r=/^[^\x25]+/.exec(n)))t.push(r[0]);else if(null!==(r=/^\x25{2}/.exec(n)))t.push("%");else{if(null===(r=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(n)))throw new Error("[_.sprintf] huh?");if(r[2]){u|=1;var i=[],l=r[2],o=[];if(null===(o=/^([a-z_][a-z_\d]*)/i.exec(l)))throw new Error("[_.sprintf] huh?");for(i.push(o[1]);""!==(l=l.substring(o[0].length));)if(null!==(o=/^\.([a-z_][a-z_\d]*)/i.exec(l)))i.push(o[1]);else{if(null===(o=/^\[(\d+)\]/.exec(l)))throw new Error("[_.sprintf] huh?");i.push(o[1])}r[2]=i}else u|=2;if(3===u)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");t.push(r)}n=n.substring(r[0].length)}return t},t}(),g={VERSION:"2.3.0",isBlank:function(e){return null==e&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return null==e?"":n(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=null==e?"":n(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,r){return null==e?[]:(e=n(e),r=~~r,r>0?e.match(new RegExp(".{1,"+r+"}","g")):[e])},clean:function(e){return g.strip(e).replace(/\s+/g," ")},count:function(e,r){if(null==e||null==r)return 0;e=n(e),r=n(r);for(var t=0,u=0,i=r.length;;){if(u=e.indexOf(r,u),-1===u)break;t++,u+=i}return t},chars:function(e){return null==e?[]:n(e).split("")},swapCase:function(e){return null==e?"":n(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return null==e?"":n(e).replace(/[&<>"']/g,function(e){return"&"+f[e]+";"})},unescapeHTML:function(e){return null==e?"":n(e).replace(/\&([^;]+);/g,function(e,r){var t;return r in s?s[r]:(t=r.match(/^#x([\da-fA-F]+)$/))?n.fromCharCode(parseInt(t[1],16)):(t=r.match(/^#(\d+)$/))?n.fromCharCode(~~t[1]):e})},escapeRegExp:function(e){return null==e?"":n(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,n,r,t){var u=g.chars(e);return u.splice(~~n,~~r,t),u.join("")},insert:function(e,n,r){return g.splice(e,n,0,r)},include:function(e,r){return""===r?!0:null==e?!1:-1!==n(e).indexOf(r)},join:function(){var e=a.call(arguments),n=e.shift();return null==n&&(n=""),e.join(n)},lines:function(e){return null==e?[]:n(e).split("\n")},reverse:function(e){return g.chars(e).reverse().join("")},startsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(0,r.length)===r)},endsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(e.length-r.length)===r)},succ:function(e){return null==e?"":(e=n(e),e.slice(0,-1)+n.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return null==e?"":(e=n(e).toLowerCase(),e.replace(/(?:^|\s|-)\S/g,function(e){return e.toUpperCase()}))},camelize:function(e){return g.trim(e).replace(/[-_\s]+(.)?/g,function(e,n){return n?n.toUpperCase():""})},underscored:function(e){return g.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return g.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return g.titleize(n(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return g.capitalize(g.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return null==e?"":!r&&t?t.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,r){return null==e?"":!r&&i?i.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+"),""))},rtrim:function(e,r){return null==e?"":!r&&u?u.call(e):(r=c(r),n(e).replace(new RegExp(r+"+$"),""))},truncate:function(e,r,t){return null==e?"":(e=n(e),t=t||"...",r=~~r,e.length>r?e.slice(0,r)+t:e)},prune:function(e,r,t){if(null==e)return"";if(e=n(e),r=~~r,t=null!=t?n(t):"...",r>=e.length)return e;var u=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},i=e.slice(0,r+1).replace(/.(?=\W*\w*$)/g,u);return i=i.slice(i.length-2).match(/\w\w/)?i.replace(/\s*\S+$/,""):g.rtrim(i.slice(0,i.length-1)),(i+t).length>e.length?e:e.slice(0,i.length)+t},words:function(e,n){return g.isBlank(e)?[]:g.trim(e,n).split(n||/\s+/)},pad:function(e,r,t,u){e=null==e?"":n(e),r=~~r;var i=0;switch(t?t.length>1&&(t=t.charAt(0)):t=" ",u){case"right":return i=r-e.length,e+o(t,i);case"both":return i=r-e.length,o(t,Math.ceil(i/2))+e+o(t,Math.floor(i/2));default:return i=r-e.length,o(t,i)+e}},lpad:function(e,n,r){return g.pad(e,n,r)},rpad:function(e,n,r){return g.pad(e,n,r,"right")},lrpad:function(e,n,r){return g.pad(e,n,r,"both")},sprintf:h,vsprintf:function(e,n){return n.unshift(e),h.apply(null,n)},toNumber:function(e,n){return e?(e=g.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?l(l(e).toFixed(~~n)):0/0):0},numberFormat:function(e,n,r,t){if(isNaN(e)||null==e)return"";e=e.toFixed(~~n),t="string"==typeof t?t:",";var u=e.split("."),i=u[0],l=u[1]?(r||".")+u[1]:"";return i.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+t)+l},strRight:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strRightBack:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.lastIndexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strLeft:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(0,t):e},strLeftBack:function(e,n){if(null==e)return"";e+="",n=null!=n?""+n:n;var r=e.lastIndexOf(n);return~r?e.slice(0,r):e},toSentence:function(e,n,r,t){n=n||", ",r=r||" and ";var u=e.slice(),i=u.pop();return e.length>2&&t&&(r=g.rtrim(n)+r),u.length?u.join(n)+r+i:i},toSentenceSerial:function(){var e=a.call(arguments);return e[3]=!0,g.toSentence.apply(g,e)},slugify:function(e){if(null==e)return"";var r="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",t="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",u=new RegExp(c(r),"g");return e=n(e).toLowerCase().replace(u,function(e){var n=r.indexOf(e);return t.charAt(n)||"-"}),g.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,n){return[n,e,n].join("")},quote:function(e,n){return g.surround(e,n||'"')},unquote:function(e,n){return n=n||'"',e[0]===n&&e[e.length-1]===n?e.slice(1,e.length-1):e},exports:function(){var e={};for(var n in this)this.hasOwnProperty(n)&&!n.match(/^(?:include|contains|reverse)$/)&&(e[n]=this[n]);return e},repeat:function(e,r,t){if(null==e)return"";if(r=~~r,null==t)return o(n(e),r);for(var u=[];r>0;u[--r]=e);return u.join(t)},naturalCmp:function(e,r){if(e==r)return 0;if(!e)return-1;if(!r)return 1;for(var t=/(\.\d+)|(\d+)|(\D+)/g,u=n(e).toLowerCase().match(t),i=n(r).toLowerCase().match(t),l=Math.min(u.length,i.length),o=0;l>o;o++){var a=u[o],c=i[o];if(a!==c){var s=parseInt(a,10);if(!isNaN(s)){var f=parseInt(c,10);if(!isNaN(f)&&s-f)return s-f}return c>a?-1:1}}return u.length===i.length?u.length-i.length:r>e?-1:1},levenshtein:function(e,r){if(null==e&&null==r)return 0;if(null==e)return n(r).length;if(null==r)return n(e).length;e=n(e),r=n(r);for(var t,u,i=[],l=0;r.length>=l;l++)for(var o=0;e.length>=o;o++)u=l&&o?e.charAt(o-1)===r.charAt(l-1)?t:Math.min(i[o],i[o-1],t)+1:l+o,t=i[o],i[o]=u;return i.pop()},toBoolean:function(e,n,t){return"number"==typeof e&&(e=""+e),"string"!=typeof e?!!e:(e=g.trim(e),r(e,n||["true","1"])?!0:r(e,t||["false","0"])?!1:void 0)}};g.strip=g.trim,g.lstrip=g.ltrim,g.rstrip=g.rtrim,g.center=g.lrpad,g.rjust=g.lpad,g.ljust=g.rpad,g.contains=g.include,g.q=g.quote,g.toBool=g.toBoolean,"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(module.exports=g),exports._s=g),"function"==typeof define&&define.amd&&define("underscore.string",[],function(){return g}),e._=e._||{},e._.string=e._.str=g}(this,String); \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/lib/underscore.string.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/lib/underscore.string.js new file mode 100644 index 000000000..87611173b --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/lib/underscore.string.js @@ -0,0 +1,673 @@ +// Underscore.string +// (c) 2010 Esa-Matti Suuronen +// Underscore.string is freely distributable under the terms of the MIT license. +// Documentation: https://github.com/epeli/underscore.string +// Some code is borrowed from MooTools and Alexandru Marasteanu. +// Version '2.3.2' + +!function(root, String){ + 'use strict'; + + // Defining helper functions. + + var nativeTrim = String.prototype.trim; + var nativeTrimRight = String.prototype.trimRight; + var nativeTrimLeft = String.prototype.trimLeft; + + var parseNumber = function(source) { return source * 1 || 0; }; + + var strRepeat = function(str, qty){ + if (qty < 1) return ''; + var result = ''; + while (qty > 0) { + if (qty & 1) result += str; + qty >>= 1, str += str; + } + return result; + }; + + var slice = [].slice; + + var defaultToWhiteSpace = function(characters) { + if (characters == null) + return '\\s'; + else if (characters.source) + return characters.source; + else + return '[' + _s.escapeRegExp(characters) + ']'; + }; + + // Helper for toBoolean + function boolMatch(s, matchers) { + var i, matcher, down = s.toLowerCase(); + matchers = [].concat(matchers); + for (i = 0; i < matchers.length; i += 1) { + matcher = matchers[i]; + if (!matcher) continue; + if (matcher.test && matcher.test(s)) return true; + if (matcher.toLowerCase() === down) return true; + } + } + + var escapeChars = { + lt: '<', + gt: '>', + quot: '"', + amp: '&', + apos: "'" + }; + + var reversedEscapeChars = {}; + for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key; + reversedEscapeChars["'"] = '#39'; + + // sprintf() for JavaScript 0.7-beta1 + // http://www.diveintojavascript.com/projects/javascript-sprintf + // + // Copyright (c) Alexandru Marasteanu + // All rights reserved. + + var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + + var str_repeat = strRepeat; + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw new Error('[_.sprintf] huh?'); + } + } + } + else { + throw new Error('[_.sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw new Error('[_.sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; + })(); + + + + // Defining underscore.string + + var _s = { + + VERSION: '2.3.0', + + isBlank: function(str){ + if (str == null) str = ''; + return (/^\s*$/).test(str); + }, + + stripTags: function(str){ + if (str == null) return ''; + return String(str).replace(/<\/?[^>]+>/g, ''); + }, + + capitalize : function(str){ + str = str == null ? '' : String(str); + return str.charAt(0).toUpperCase() + str.slice(1); + }, + + chop: function(str, step){ + if (str == null) return []; + str = String(str); + step = ~~step; + return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str]; + }, + + clean: function(str){ + return _s.strip(str).replace(/\s+/g, ' '); + }, + + count: function(str, substr){ + if (str == null || substr == null) return 0; + + str = String(str); + substr = String(substr); + + var count = 0, + pos = 0, + length = substr.length; + + while (true) { + pos = str.indexOf(substr, pos); + if (pos === -1) break; + count++; + pos += length; + } + + return count; + }, + + chars: function(str) { + if (str == null) return []; + return String(str).split(''); + }, + + swapCase: function(str) { + if (str == null) return ''; + return String(str).replace(/\S/g, function(c){ + return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase(); + }); + }, + + escapeHTML: function(str) { + if (str == null) return ''; + return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }); + }, + + unescapeHTML: function(str) { + if (str == null) return ''; + return String(str).replace(/\&([^;]+);/g, function(entity, entityCode){ + var match; + + if (entityCode in escapeChars) { + return escapeChars[entityCode]; + } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { + return String.fromCharCode(parseInt(match[1], 16)); + } else if (match = entityCode.match(/^#(\d+)$/)) { + return String.fromCharCode(~~match[1]); + } else { + return entity; + } + }); + }, + + escapeRegExp: function(str){ + if (str == null) return ''; + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); + }, + + splice: function(str, i, howmany, substr){ + var arr = _s.chars(str); + arr.splice(~~i, ~~howmany, substr); + return arr.join(''); + }, + + insert: function(str, i, substr){ + return _s.splice(str, i, 0, substr); + }, + + include: function(str, needle){ + if (needle === '') return true; + if (str == null) return false; + return String(str).indexOf(needle) !== -1; + }, + + join: function() { + var args = slice.call(arguments), + separator = args.shift(); + + if (separator == null) separator = ''; + + return args.join(separator); + }, + + lines: function(str) { + if (str == null) return []; + return String(str).split("\n"); + }, + + reverse: function(str){ + return _s.chars(str).reverse().join(''); + }, + + startsWith: function(str, starts){ + if (starts === '') return true; + if (str == null || starts == null) return false; + str = String(str); starts = String(starts); + return str.length >= starts.length && str.slice(0, starts.length) === starts; + }, + + endsWith: function(str, ends){ + if (ends === '') return true; + if (str == null || ends == null) return false; + str = String(str); ends = String(ends); + return str.length >= ends.length && str.slice(str.length - ends.length) === ends; + }, + + succ: function(str){ + if (str == null) return ''; + str = String(str); + return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1); + }, + + titleize: function(str){ + if (str == null) return ''; + str = String(str).toLowerCase(); + return str.replace(/(?:^|\s|-)\S/g, function(c){ return c.toUpperCase(); }); + }, + + camelize: function(str){ + return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : ""; }); + }, + + underscored: function(str){ + return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); + }, + + dasherize: function(str){ + return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase(); + }, + + classify: function(str){ + return _s.titleize(String(str).replace(/[\W_]/g, ' ')).replace(/\s/g, ''); + }, + + humanize: function(str){ + return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' ')); + }, + + trim: function(str, characters){ + if (str == null) return ''; + if (!characters && nativeTrim) return nativeTrim.call(str); + characters = defaultToWhiteSpace(characters); + return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), ''); + }, + + ltrim: function(str, characters){ + if (str == null) return ''; + if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str); + characters = defaultToWhiteSpace(characters); + return String(str).replace(new RegExp('^' + characters + '+'), ''); + }, + + rtrim: function(str, characters){ + if (str == null) return ''; + if (!characters && nativeTrimRight) return nativeTrimRight.call(str); + characters = defaultToWhiteSpace(characters); + return String(str).replace(new RegExp(characters + '+$'), ''); + }, + + truncate: function(str, length, truncateStr){ + if (str == null) return ''; + str = String(str); truncateStr = truncateStr || '...'; + length = ~~length; + return str.length > length ? str.slice(0, length) + truncateStr : str; + }, + + /** + * _s.prune: a more elegant version of truncate + * prune extra chars, never leaving a half-chopped word. + * @author github.com/rwz + */ + prune: function(str, length, pruneStr){ + if (str == null) return ''; + + str = String(str); length = ~~length; + pruneStr = pruneStr != null ? String(pruneStr) : '...'; + + if (str.length <= length) return str; + + var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; }, + template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' + + if (template.slice(template.length-2).match(/\w\w/)) + template = template.replace(/\s*\S+$/, ''); + else + template = _s.rtrim(template.slice(0, template.length-1)); + + return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr; + }, + + words: function(str, delimiter) { + if (_s.isBlank(str)) return []; + return _s.trim(str, delimiter).split(delimiter || /\s+/); + }, + + pad: function(str, length, padStr, type) { + str = str == null ? '' : String(str); + length = ~~length; + + var padlen = 0; + + if (!padStr) + padStr = ' '; + else if (padStr.length > 1) + padStr = padStr.charAt(0); + + switch(type) { + case 'right': + padlen = length - str.length; + return str + strRepeat(padStr, padlen); + case 'both': + padlen = length - str.length; + return strRepeat(padStr, Math.ceil(padlen/2)) + str + + strRepeat(padStr, Math.floor(padlen/2)); + default: // 'left' + padlen = length - str.length; + return strRepeat(padStr, padlen) + str; + } + }, + + lpad: function(str, length, padStr) { + return _s.pad(str, length, padStr); + }, + + rpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'right'); + }, + + lrpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'both'); + }, + + sprintf: sprintf, + + vsprintf: function(fmt, argv){ + argv.unshift(fmt); + return sprintf.apply(null, argv); + }, + + toNumber: function(str, decimals) { + if (!str) return 0; + str = _s.trim(str); + if (!str.match(/^-?\d+(?:\.\d+)?$/)) return NaN; + return parseNumber(parseNumber(str).toFixed(~~decimals)); + }, + + numberFormat : function(number, dec, dsep, tsep) { + if (isNaN(number) || number == null) return ''; + + number = number.toFixed(~~dec); + tsep = typeof tsep == 'string' ? tsep : ','; + + var parts = number.split('.'), fnums = parts[0], + decimals = parts[1] ? (dsep || '.') + parts[1] : ''; + + return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals; + }, + + strRight: function(str, sep){ + if (str == null) return ''; + str = String(str); sep = sep != null ? String(sep) : sep; + var pos = !sep ? -1 : str.indexOf(sep); + return ~pos ? str.slice(pos+sep.length, str.length) : str; + }, + + strRightBack: function(str, sep){ + if (str == null) return ''; + str = String(str); sep = sep != null ? String(sep) : sep; + var pos = !sep ? -1 : str.lastIndexOf(sep); + return ~pos ? str.slice(pos+sep.length, str.length) : str; + }, + + strLeft: function(str, sep){ + if (str == null) return ''; + str = String(str); sep = sep != null ? String(sep) : sep; + var pos = !sep ? -1 : str.indexOf(sep); + return ~pos ? str.slice(0, pos) : str; + }, + + strLeftBack: function(str, sep){ + if (str == null) return ''; + str += ''; sep = sep != null ? ''+sep : sep; + var pos = str.lastIndexOf(sep); + return ~pos ? str.slice(0, pos) : str; + }, + + toSentence: function(array, separator, lastSeparator, serial) { + separator = separator || ', '; + lastSeparator = lastSeparator || ' and '; + var a = array.slice(), lastMember = a.pop(); + + if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator; + + return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember; + }, + + toSentenceSerial: function() { + var args = slice.call(arguments); + args[3] = true; + return _s.toSentence.apply(_s, args); + }, + + slugify: function(str) { + if (str == null) return ''; + + var from = "ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź", + to = "aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz", + regex = new RegExp(defaultToWhiteSpace(from), 'g'); + + str = String(str).toLowerCase().replace(regex, function(c){ + var index = from.indexOf(c); + return to.charAt(index) || '-'; + }); + + return _s.dasherize(str.replace(/[^\w\s-]/g, '')); + }, + + surround: function(str, wrapper) { + return [wrapper, str, wrapper].join(''); + }, + + quote: function(str, quoteChar) { + return _s.surround(str, quoteChar || '"'); + }, + + unquote: function(str, quoteChar) { + quoteChar = quoteChar || '"'; + if (str[0] === quoteChar && str[str.length-1] === quoteChar) + return str.slice(1,str.length-1); + else return str; + }, + + exports: function() { + var result = {}; + + for (var prop in this) { + if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue; + result[prop] = this[prop]; + } + + return result; + }, + + repeat: function(str, qty, separator){ + if (str == null) return ''; + + qty = ~~qty; + + // using faster implementation if separator is not needed; + if (separator == null) return strRepeat(String(str), qty); + + // this one is about 300x slower in Google Chrome + for (var repeat = []; qty > 0; repeat[--qty] = str) {} + return repeat.join(separator); + }, + + naturalCmp: function(str1, str2){ + if (str1 == str2) return 0; + if (!str1) return -1; + if (!str2) return 1; + + var cmpRegex = /(\.\d+)|(\d+)|(\D+)/g, + tokens1 = String(str1).toLowerCase().match(cmpRegex), + tokens2 = String(str2).toLowerCase().match(cmpRegex), + count = Math.min(tokens1.length, tokens2.length); + + for(var i = 0; i < count; i++) { + var a = tokens1[i], b = tokens2[i]; + + if (a !== b){ + var num1 = parseInt(a, 10); + if (!isNaN(num1)){ + var num2 = parseInt(b, 10); + if (!isNaN(num2) && num1 - num2) + return num1 - num2; + } + return a < b ? -1 : 1; + } + } + + if (tokens1.length === tokens2.length) + return tokens1.length - tokens2.length; + + return str1 < str2 ? -1 : 1; + }, + + levenshtein: function(str1, str2) { + if (str1 == null && str2 == null) return 0; + if (str1 == null) return String(str2).length; + if (str2 == null) return String(str1).length; + + str1 = String(str1); str2 = String(str2); + + var current = [], prev, value; + + for (var i = 0; i <= str2.length; i++) + for (var j = 0; j <= str1.length; j++) { + if (i && j) + if (str1.charAt(j - 1) === str2.charAt(i - 1)) + value = prev; + else + value = Math.min(current[j], current[j - 1], prev) + 1; + else + value = i + j; + + prev = current[j]; + current[j] = value; + } + + return current.pop(); + }, + + toBoolean: function(str, trueValues, falseValues) { + if (typeof str === "number") str = "" + str; + if (typeof str !== "string") return !!str; + str = _s.trim(str); + if (boolMatch(str, trueValues || ["true", "1"])) return true; + if (boolMatch(str, falseValues || ["false", "0"])) return false; + } + }; + + // Aliases + + _s.strip = _s.trim; + _s.lstrip = _s.ltrim; + _s.rstrip = _s.rtrim; + _s.center = _s.lrpad; + _s.rjust = _s.lpad; + _s.ljust = _s.rpad; + _s.contains = _s.include; + _s.q = _s.quote; + _s.toBool = _s.toBoolean; + + // Exporting + + // CommonJS module is defined + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) + module.exports = _s; + + exports._s = _s; + } + + // Register as a named module with AMD. + if (typeof define === 'function' && define.amd) + define('underscore.string', [], function(){ return _s; }); + + + // Integrate with Underscore.js if defined + // or create our own underscore object. + root._ = root._ || {}; + root._.string = root._.str = _s; +}(this, String); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/libpeerconnection.log b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/libpeerconnection.log new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/package.json b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/package.json new file mode 100644 index 000000000..98b225275 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/package.json @@ -0,0 +1,77 @@ +{ + "name": "underscore.string", + "version": "2.3.3", + "description": "String manipulation extensions for Underscore.js javascript library.", + "homepage": "http://epeli.github.com/underscore.string/", + "contributors": [ + { + "name": "Esa-Matti Suuronen", + "email": "esa-matti@suuronen.org", + "url": "http://esa-matti.suuronen.org/" + }, + { + "name": "Edward Tsech", + "email": "edtsech@gmail.com" + }, + { + "name": "Pavel Pravosud", + "email": "pavel@pravosud.com", + "url": "" + }, + { + "name": "Sasha Koss", + "email": "kossnocorp@gmail.com", + "url": "http://koss.nocorp.me/" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Pete Kruckenberg", + "email": "https://github.com/kruckenb", + "url": "" + }, + { + "name": "Paul Chavard", + "email": "paul@chavard.net", + "url": "" + }, + { + "name": "Ed Finkler", + "email": "coj@funkatron.com", + "url": "" + } + ], + "keywords": [ + "underscore", + "string" + ], + "main": "./lib/underscore.string", + "directories": { + "lib": "./lib" + }, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/epeli/underscore.string.git" + }, + "bugs": { + "url": "https://github.com/epeli/underscore.string/issues" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "readme": "# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) #\n\n\n\nJavascript lacks complete string manipulation operations.\nThis an attempt to fill that gap. List of build-in methods can be found\nfor example from [Dive Into JavaScript][d].\n\n[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object\n\n\nAs name states this an extension for [Underscore.js][u], but it can be used\nindependently from **_s**-global variable. But with Underscore.js you can\nuse Object-Oriented style and chaining:\n\n[u]: http://documentcloud.github.com/underscore/\n\n```javascript\n_(\" epeli \").chain().trim().capitalize().value()\n=> \"Epeli\"\n```\n\n## Download ##\n\n * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb*\n * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb*\n\n\n## Node.js installation ##\n\n**npm package**\n\n npm install underscore.string\n\n**Standalone usage**:\n\n```javascript\nvar _s = require('underscore.string');\n```\n\n**Integrate with Underscore.js**:\n\n```javascript\nvar _ = require('underscore');\n\n// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)\n_.str = require('underscore.string');\n\n// Mix in non-conflict functions to Underscore namespace if you want\n_.mixin(_.str.exports());\n\n// All functions, include conflict, will be available through _.str object\n_.str.include('Underscore.string', 'string'); // => true\n```\n\n**Or Integrate with Underscore.js without module loading**\n\nRun the following expression after Underscore.js and Underscore.string are loaded\n```javascript\n// _.str becomes a global variable if no module loading is detected\n// Mix in non-conflict functions to Underscore namespace\n_.mixin(_.str.exports());\n```\n\n## String Functions ##\n\nFor availability of functions in this way you need to mix in Underscore.string functions:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\notherwise functions from examples will be available through _.string or _.str objects:\n\n```javascript\n_.str.capitalize('epeli')\n=> \"Epeli\"\n```\n\n**numberFormat** _.numberFormat(number, [ decimals=0, decimalSeparator='.', orderSeparator=','])\n\nFormats the numbers.\n\n```javascript\n_.numberFormat(1000, 2)\n=> \"1,000.00\"\n\n_.numberFormat(123456789.123, 5, '.', ',')\n=> \"123,456,789.12300\"\n```\n\n\n**levenshtein** _.levenshtein(string1, string2)\n\nCalculates [Levenshtein distance][ld] between two strings.\n[ld]: http://en.wikipedia.org/wiki/Levenshtein_distance\n\n```javascript\n_.levenshtein('kitten', 'kittah')\n=> 2\n```\n\n**capitalize** _.capitalize(string)\n\nConverts first letter of the string to uppercase.\n\n```javascript\n_.capitalize(\"foo Bar\")\n=> \"Foo Bar\"\n```\n\n**chop** _.chop(string, step)\n\n```javascript\n_.chop('whitespace', 3)\n=> ['whi','tes','pac','e']\n```\n\n**clean** _.clean(str)\n\nCompress some whitespaces to one.\n\n```javascript\n_.clean(\" foo bar \")\n=> 'foo bar'\n```\n\n**chars** _.chars(str)\n\n```javascript\n_.chars('Hello')\n=> ['H','e','l','l','o']\n```\n\n**swapCase** _.swapCase(str)\n\nReturns a copy of the string in which all the case-based characters have had their case swapped.\n\n```javascript\n_.swapCase('hELLO')\n=> 'Hello'\n```\n\n**include** available only through _.str object, because Underscore has function with the same name.\n\n```javascript\n_.str.include(\"foobar\", \"ob\")\n=> true\n```\n\n(removed) **includes** _.includes(string, substring)\n\nTests if string contains a substring.\n\n```javascript\n_.includes(\"foobar\", \"ob\")\n=> true\n```\n\n**includes** function was removed\n\nBut you can create it in this way, for compatibility with previous versions:\n\n```javascript\n_.includes = _.str.include\n```\n\n**count** _.count(string, substring)\n\n```javascript\n_('Hello world').count('l')\n=> 3\n```\n\n**escapeHTML** _.escapeHTML(string)\n\nConverts HTML special characters to their entity equivalents.\n\n```javascript\n_('
      Blah blah blah
      ').escapeHTML();\n=> '<div>Blah blah blah</div>'\n```\n\n**unescapeHTML** _.unescapeHTML(string)\n\nConverts entity characters to HTML equivalents.\n\n```javascript\n_('<div>Blah blah blah</div>').unescapeHTML();\n=> '
      Blah blah blah
      '\n```\n\n**insert** _.insert(string, index, substing)\n\n```javascript\n_('Hello ').insert(6, 'world')\n=> 'Hello world'\n```\n\n**isBlank** _.isBlank(string)\n\n```javascript\n_('').isBlank(); // => true\n_('\\n').isBlank(); // => true\n_(' ').isBlank(); // => true\n_('a').isBlank(); // => false\n```\n\n**join** _.join(separator, *strings)\n\nJoins strings together with given separator\n\n```javascript\n_.join(\" \", \"foo\", \"bar\")\n=> \"foo bar\"\n```\n\n**lines** _.lines(str)\n\n```javascript\n_.lines(\"Hello\\nWorld\")\n=> [\"Hello\", \"World\"]\n```\n\n**reverse** available only through _.str object, because Underscore has function with the same name.\n\nReturn reversed string:\n\n```javascript\n_.str.reverse(\"foobar\")\n=> 'raboof'\n```\n\n**splice** _.splice(string, index, howmany, substring)\n\nLike a array splice.\n\n```javascript\n_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli')\n=> 'https://edtsech@bitbucket.org/epeli/underscore.strings'\n```\n\n**startsWith** _.startsWith(string, starts)\n\nThis method checks whether string starts with starts.\n\n```javascript\n_(\"image.gif\").startsWith(\"image\")\n=> true\n```\n\n**endsWith** _.endsWith(string, ends)\n\nThis method checks whether string ends with ends.\n\n```javascript\n_(\"image.gif\").endsWith(\"gif\")\n=> true\n```\n\n**succ** _.succ(str)\n\nReturns the successor to str.\n\n```javascript\n_('a').succ()\n=> 'b'\n\n_('A').succ()\n=> 'B'\n```\n\n**supplant**\n\nSupplant function was removed, use Underscore.js [template function][p].\n\n[p]: http://documentcloud.github.com/underscore/#template\n\n**strip** alias for *trim*\n\n**lstrip** alias for *ltrim*\n\n**rstrip** alias for *rtrim*\n\n**titleize** _.titleize(string)\n\n```javascript\n_('my name is epeli').titleize()\n=> 'My Name Is Epeli'\n```\n\n**camelize** _.camelize(string)\n\nConverts underscored or dasherized string to a camelized one\n\n```javascript\n_('-moz-transform').camelize()\n=> 'MozTransform'\n```\n\n**classify** _.classify(string)\n\nConverts string to camelized class name\n\n```javascript\n_('some_class_name').classify()\n=> 'SomeClassName'\n```\n\n**underscored** _.underscored(string)\n\nConverts a camelized or dasherized string into an underscored one\n\n```javascript\n_('MozTransform').underscored()\n=> 'moz_transform'\n```\n\n**dasherize** _.dasherize(string)\n\nConverts a underscored or camelized string into an dasherized one\n\n```javascript\n_('MozTransform').dasherize()\n=> '-moz-transform'\n```\n\n**humanize** _.humanize(string)\n\nConverts an underscored, camelized, or dasherized string into a humanized one.\nAlso removes beginning and ending whitespace, and removes the postfix '_id'.\n\n```javascript\n_(' capitalize dash-CamelCase_underscore trim ').humanize()\n=> 'Capitalize dash camel case underscore trim'\n```\n\n**trim** _.trim(string, [characters])\n\ntrims defined characters from begining and ending of the string.\nDefaults to whitespace characters.\n\n```javascript\n_.trim(\" foobar \")\n=> \"foobar\"\n\n_.trim(\"_-foobar-_\", \"_-\")\n=> \"foobar\"\n```\n\n\n**ltrim** _.ltrim(string, [characters])\n\nLeft trim. Similar to trim, but only for left side.\n\n\n**rtrim** _.rtrim(string, [characters])\n\nRight trim. Similar to trim, but only for right side.\n\n**truncate** _.truncate(string, length, truncateString)\n\n```javascript\n_('Hello world').truncate(5)\n=> 'Hello...'\n\n_('Hello').truncate(10)\n=> 'Hello'\n```\n\n**prune** _.prune(string, length, pruneString)\n\nElegant version of truncate.\nMakes sure the pruned string does not exceed the original length.\nAvoid half-chopped words when truncating.\n\n```javascript\n_('Hello, world').prune(5)\n=> 'Hello...'\n\n_('Hello, world').prune(8)\n=> 'Hello...'\n\n_('Hello, world').prune(5, ' (read a lot more)')\n=> 'Hello, world' (as adding \"(read a lot more)\" would be longer than the original string)\n\n_('Hello, cruel world').prune(15)\n=> 'Hello, cruel...'\n\n_('Hello').prune(10)\n=> 'Hello'\n```\n\n**words** _.words(str, delimiter=/\\s+/)\n\nSplit string by delimiter (String or RegExp), /\\s+/ by default.\n\n```javascript\n_.words(\" I love you \")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I_love_you\", \"_\")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I-love-you\", /-/)\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\" \")\n=> []\n```\n\n**sprintf** _.sprintf(string format, *arguments)\n\nC like string formatting.\nCredits goes to [Alexandru Marasteanu][o].\nFor more detailed documentation, see the [original page][o].\n\n[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript\n\n```javascript\n_.sprintf(\"%.1f\", 1.17)\n\"1.2\"\n```\n\n**pad** _.pad(str, length, [padStr, type])\n\npads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`\" \"`). `padStr` is truncated to a single character if necessary.\n\n```javascript\n_.pad(\"1\", 8)\n-> \" 1\";\n\n_.pad(\"1\", 8, '0')\n-> \"00000001\";\n\n_.pad(\"1\", 8, '0', 'right')\n-> \"10000000\";\n\n_.pad(\"1\", 8, '0', 'both')\n-> \"00001000\";\n\n_.pad(\"1\", 8, 'bleepblorp', 'both')\n-> \"bbbb1bbb\";\n```\n\n**lpad** _.lpad(str, length, [padStr])\n\nleft-pad a string. Alias for `pad(str, length, padStr, 'left')`\n\n```javascript\n_.lpad(\"1\", 8, '0')\n-> \"00000001\";\n```\n\n**rpad** _.rpad(str, length, [padStr])\n\nright-pad a string. Alias for `pad(str, length, padStr, 'right')`\n\n```javascript\n_.rpad(\"1\", 8, '0')\n-> \"10000000\";\n```\n\n**lrpad** _.lrpad(str, length, [padStr])\n\nleft/right-pad a string. Alias for `pad(str, length, padStr, 'both')`\n\n```javascript\n_.lrpad(\"1\", 8, '0')\n-> \"00001000\";\n```\n\n**center** alias for **lrpad**\n\n**ljust** alias for *rpad*\n\n**rjust** alias for *lpad*\n\n**toNumber** _.toNumber(string, [decimals])\n\nParse string to number. Returns NaN if string can't be parsed to number.\n\n```javascript\n_('2.556').toNumber()\n=> 3\n\n_('2.556').toNumber(1)\n=> 2.6\n```\n\n**strRight** _.strRight(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRight('_')\n=> \"is_a_test_string\";\n```\n\n**strRightBack** _.strRightBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRightBack('_')\n=> \"string\";\n```\n\n**strLeft** _.strLeft(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeft('_')\n=> \"This\";\n```\n\n**strLeftBack** _.strLeftBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeftBack('_')\n=> \"This_is_a_test\";\n```\n\n**stripTags**\n\nRemoves all html tags from string.\n\n```javascript\n_('a link').stripTags()\n=> 'a link'\n\n_('a link').stripTags()\n=> 'a linkalert(\"hello world!\")'\n```\n\n**toSentence** _.toSentence(array, [delimiter, lastDelimiter])\n\nJoin an array into a human readable sentence.\n\n```javascript\n_.toSentence(['jQuery', 'Mootools', 'Prototype'])\n=> 'jQuery, Mootools and Prototype';\n\n_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ')\n=> 'jQuery, Mootools unt Prototype';\n```\n\n**toSentenceSerial** _.toSentenceSerial(array, [delimiter, lastDelimiter])\n\nThe same as `toSentence`, but adjusts delimeters to use [Serial comma](http://en.wikipedia.org/wiki/Serial_comma).\n\n```javascript\n_.toSentenceSerial(['jQuery', 'Mootools'])\n=> 'jQuery and Mootools';\n\n_.toSentenceSerial(['jQuery', 'Mootools', 'Prototype'])\n=> 'jQuery, Mootools, and Prototype'\n\n_.toSentenceSerial(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ');\n=> 'jQuery, Mootools, unt Prototype';\n```\n\n**repeat** _.repeat(string, count, [separator])\n\nRepeats a string count times.\n\n```javascript\n_.repeat(\"foo\", 3)\n=> 'foofoofoo';\n\n_.repeat(\"foo\", 3, \"bar\")\n=> 'foobarfoobarfoo'\n```\n\n**surround** _.surround(string, wrap)\n\nSurround a string with another string.\n\n```javascript\n_.surround(\"foo\", \"ab\")\n=> 'abfooab';\n```\n\n**quote** _.quote(string, quoteChar) or _.q(string, quoteChar)\n\nQuotes a string. `quoteChar` defaults to `\"`.\n\n```javascript\n_.quote('foo', quoteChar)\n=> '\"foo\"';\n```\n**unquote** _.unquote(string, quoteChar)\n\nUnquotes a string. `quoteChar` defaults to `\"`.\n\n```javascript\n_.unquote('\"foo\"')\n=> 'foo';\n_.unquote(\"'foo'\", \"'\")\n=> 'foo';\n```\n\n\n**slugify** _.slugify(string)\n\nTransform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash.\n\n```javascript\n_.slugify(\"Un éléphant à l'orée du bois\")\n=> 'un-elephant-a-loree-du-bois';\n```\n\n***Caution: this function is charset dependent***\n\n**naturalCmp** array.sort(_.naturalCmp)\n\nNaturally sort strings like humans would do.\n\n```javascript\n['foo20', 'foo5'].sort(_.naturalCmp)\n=> [ 'foo5', 'foo20' ]\n```\n\n**toBoolean** _.toBoolean(string) or _.toBool(string)\n\nTurn strings that can be commonly considered as booleas to real booleans. Such as \"true\", \"false\", \"1\" and \"0\". This function is case insensitive.\n\n```javascript\n_.toBoolean(\"true\")\n=> true\n_.toBoolean(\"FALSE\")\n=> false\n_.toBoolean(\"random\")\n=> undefined\n```\n\nIt can be customized by giving arrays of truth and falsy value matcher as parameters. Matchers can be also RegExp objects.\n\n```javascript\n_.toBoolean(\"truthy\", [\"truthy\"], [\"falsy\"])\n=> true\n_.toBoolean(\"true only at start\", [/^true/])\n=> true\n```\n\n## Roadmap ##\n\nAny suggestions or bug reports are welcome. Just email me or more preferably open an issue.\n\n#### Problems\n\nWe lose two things for `include` and `reverse` methods from `_.string`:\n\n* Calls like `_('foobar').include('bar')` aren't available;\n* Chaining isn't available too.\n\nBut if you need this functionality you can create aliases for conflict functions which will be convenient for you:\n\n```javascript\n_.mixin({\n includeString: _.str.include,\n reverseString: _.str.reverse\n})\n\n// Now wrapper calls and chaining are available.\n_('foobar').chain().reverseString().includeString('rab').value()\n```\n\n#### Standalone Usage\n\nIf you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias\nBut of course you can just reassign `_` variable with `_.string`\n\n```javascript\n_ = _.string\n```\n\n## Changelog ##\n\n### 2.3.3 ###\n\n* Add `toBoolean`\n* Add `unquote`\n* Add quote char option to `quote`\n* Support dash-separated words in `titleize`\n\n### 2.3.2 ###\n\n* Add `naturalCmp`\n* Bug fix to `camelize`\n* Add ă, ș, ț and ś to `slugify`\n* Doc updates\n* Add support for [component](http://component.io/)\n* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.1...v2.3.2)\n\n### 2.3.1 ###\n\n* Bug fixes to `escapeHTML`, `classify`, `substr`\n* Faster `count`\n* Documentation fixes\n* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.0...v2.3.1)\n\n### 2.3.0 ###\n\n* Added `numberformat` method\n* Added `levenshtein` method (Levenshtein distance calculation)\n* Added `swapCase` method\n* Changed default behavior of `words` method\n* Added `toSentenceSerial` method\n* Added `surround` and `quote` methods\n\n### 2.2.1 ###\n\n* Same as 2.2.0 (2.2.0rc on npm) to fix some npm drama\n\n### 2.2.0 ###\n\n* Capitalize method behavior changed\n* Various perfomance tweaks\n\n### 2.1.1###\n\n* Fixed words method bug\n* Added classify method\n\n### 2.1.0 ###\n\n* AMD support\n* Added toSentence method\n* Added slugify method\n* Lots of speed optimizations\n\n### 2.0.0 ###\n\n* Added prune, humanize functions\n* Added _.string (_.str) namespace for Underscore.string library\n* Removed includes function\n\nFor upgrading to this version you need to mix in Underscore.string library to Underscore object:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\nand all non-conflict Underscore.string functions will be available through Underscore object.\nAlso function `includes` has been removed, you should replace this function by `_.str.include`\nor create alias `_.includes = _.str.include` and all your code will work fine.\n\n### 1.1.6 ###\n\n* Fixed reverse and truncate\n* Added isBlank, stripTags, inlude(alias for includes)\n* Added uglifier compression\n\n### 1.1.5 ###\n\n* Added strRight, strRightBack, strLeft, strLeftBack\n\n### 1.1.4 ###\n\n* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust\n* Integration with Underscore 1.1.6\n\n### 1.1.3 ###\n\n* Added methods: underscored, camelize, dasherize\n* Support newer version of npm\n\n### 1.1.2 ###\n\n* Created functions: lines, chars, words functions\n\n### 1.0.2 ###\n\n* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible)\n* Removed 'reverse' function, because this function override underscore.js 'reverse'\n\n## Contribute ##\n\n* Fork & pull request. Don't forget about tests.\n* If you planning add some feature please create issue before.\n\nOtherwise changes will be rejected.\n\n## Contributors list ##\n[Can be found here](https://github.com/epeli/underscore.string/graphs/contributors).\n\n\n## Licence ##\n\nThe MIT License\n\nCopyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org\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", + "readmeFilename": "README.markdown", + "_id": "underscore.string@2.3.3", + "dist": { + "shasum": "49ede1a30bcad624dbdac5b2701d4dc311285221" + }, + "_from": "underscore.string@~2.3.1", + "_resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz" +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/run-qunit.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/run-qunit.js new file mode 100644 index 000000000..44a216705 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/run-qunit.js @@ -0,0 +1,45 @@ +function waitFor(test, complete, timeout) { + var result, start = new Date().getTime() + setInterval(function interval() { + if ((new Date().getTime() - start < timeout) && !result) { + result = test() + } else { + if (!result) { + phantom.exit(1) + } else { + complete() + clearInterval(interval) + } + } + }, 100) +} + + +var fs = require('fs'), page = require('webpage').create(); +var url = 'file://localhost' + fs.workingDirectory + '/' + phantom.args[0]; + +page.onConsoleMessage = function(msg) { + console.log(msg) +} + +page.open(url, function(status) { + waitFor(function() { + return page.evaluate(function(){ + var el = document.getElementById('qunit-testresult') + return el && el.innerText.match('completed') + }) + }, function() { + var failures = page.evaluate(function() { + var el = document.getElementById('qunit-testresult'), + fails = document.getElementsByClassName('fail') + + for (var i = 0; i < fails.length; i++) + console.log(fails[i].innerText) + + console.log(el.innerText) + + return parseInt(el.getElementsByClassName('failed')[0].innerHTML) + }) + phantom.exit(failures > 0 ? 1 : 0) + }, 10000) +}) \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/speed.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/speed.js new file mode 100644 index 000000000..9ceeea76d --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/speed.js @@ -0,0 +1,148 @@ +(function() { + + JSLitmus.test('levenshtein', function() { + return [ + _.levenshtein('pineapple', 'potato'), + _.levenshtein('seven', 'eight'), + _.levenshtein('the very same string', 'the very same string'), + _.levenshtein('very very very long string', 'something completely different') + ]; + }); + + + JSLitmus.test('trimNoNative', function() { + return _.trim(" foobar ", " "); + }); + + JSLitmus.test('trim', function() { + return _.trim(" foobar "); + }); + + JSLitmus.test('trim object-oriented', function() { + return _(" foobar ").trim(); + }); + + JSLitmus.test('trim jQuery', function() { + return jQuery.trim(" foobar "); + }); + + JSLitmus.test('ltrimp', function() { + return _.ltrim(" foobar ", " "); + }); + + JSLitmus.test('rtrimp', function() { + return _.rtrim(" foobar ", " "); + }); + + JSLitmus.test('startsWith', function() { + return _.startsWith("foobar", "foo"); + }); + + JSLitmus.test('endsWith', function() { + return _.endsWith("foobar", "xx"); + }); + + JSLitmus.test('chop', function(){ + return _('whitespace').chop(2); + }); + + JSLitmus.test('count', function(){ + return _('Hello worls').count('l'); + }); + + JSLitmus.test('insert', function() { + return _('Hello ').insert(6, 'world'); + }); + + JSLitmus.test('splice', function() { + return _('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'); + }); + + JSLitmus.test('succ', function(){ + var let = 'a', alphabet = []; + + for (var i=0; i < 26; i++) { + alphabet.push(let); + let = _(let).succ(); + } + + return alphabet; + }); + + JSLitmus.test('titleize', function(){ + return _('the titleize string method').titleize(); + }); + + JSLitmus.test('truncate', function(){ + return _('Hello world').truncate(5); + }); + + JSLitmus.test('prune', function(){ + return _('Hello world').prune(5); + }); + + JSLitmus.test('isBlank', function(){ + return _('').isBlank(); + }); + + JSLitmus.test('escapeHTML', function(){ + _('
      Blah blah blah
      ').escapeHTML(); + }); + + JSLitmus.test('unescapeHTML', function(){ + _('<div>Blah blah blah</div>').unescapeHTML(); + }); + + JSLitmus.test('reverse', function(){ + _('Hello World').reverse(); + }); + + JSLitmus.test('pad default', function(){ + _('foo').pad(12); + }); + + JSLitmus.test('pad hash left', function(){ + _('foo').pad(12, '#'); + }); + + JSLitmus.test('pad hash right', function(){ + _('foo').pad(12, '#', 'right'); + }); + + JSLitmus.test('pad hash both', function(){ + _('foo').pad(12, '#', 'both'); + }); + + JSLitmus.test('pad hash both longPad', function(){ + _('foo').pad(12, 'f00f00f00', 'both'); + }); + + JSLitmus.test('toNumber', function(){ + _('10.232323').toNumber(2); + }); + + JSLitmus.test('strRight', function(){ + _('aaa_bbb_ccc').strRight('_'); + }); + + JSLitmus.test('strRightBack', function(){ + _('aaa_bbb_ccc').strRightBack('_'); + }); + + JSLitmus.test('strLeft', function(){ + _('aaa_bbb_ccc').strLeft('_'); + }); + + JSLitmus.test('strLeftBack', function(){ + _('aaa_bbb_ccc').strLeftBack('_'); + }); + + JSLitmus.test('join', function(){ + _('separator').join(1, 2, 3, 4, 5, 6, 7, 8, 'foo', 'bar', 'lol', 'wut'); + }); + + JSLitmus.test('slugify', function(){ + _("Un éléphant à l'orée du bois").slugify(); + }); + +})(); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/strings.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/strings.js new file mode 100644 index 000000000..77364f205 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/strings.js @@ -0,0 +1,685 @@ +$(document).ready(function() { + + // Include Underscore.string methods to Underscore namespace + _.mixin(_.str.exports()); + + module('String extensions'); + + test('Strings: naturalSort', function() { + var arr = ['foo2', 'foo1', 'foo10', 'foo30', 'foo100', 'foo10bar'], + sorted = ['foo1', 'foo2', 'foo10', 'foo10bar', 'foo30', 'foo100']; + deepEqual(arr.sort(_.naturalCmp), sorted); + }); + + test('Strings: trim', function() { + equal(_.trim(123), '123', 'Non string'); + equal(_(' foo').trim(), 'foo'); + equal(_('foo ').trim(), 'foo'); + equal(_(' foo ').trim(), 'foo'); + equal(_(' foo ').trim(), 'foo'); + equal(_(' foo ').trim(' '), 'foo', 'Manually set whitespace'); + equal(_('\t foo \t ').trim(/\s/), 'foo', 'Manually set RegExp /\\s+/'); + + equal(_('ffoo').trim('f'), 'oo'); + equal(_('ooff').trim('f'), 'oo'); + equal(_('ffooff').trim('f'), 'oo'); + + + equal(_('_-foobar-_').trim('_-'), 'foobar'); + + equal(_('http://foo/').trim('/'), 'http://foo'); + equal(_('c:\\').trim('\\'), 'c:'); + + equal(_(123).trim(), '123'); + equal(_(123).trim(3), '12'); + equal(_('').trim(), '', 'Trim empty string should return empty string'); + equal(_(null).trim(), '', 'Trim null should return empty string'); + equal(_(undefined).trim(), '', 'Trim undefined should return empty string'); + }); + + test('String: levenshtein', function() { + equal(_.levenshtein('Godfather', 'Godfather'), 0); + equal(_.levenshtein('Godfather', 'Godfathe'), 1); + equal(_.levenshtein('Godfather', 'odfather'), 1); + equal(_.levenshtein('Godfather', 'Gdfthr'), 3); + equal(_.levenshtein('seven', 'eight'), 5); + equal(_.levenshtein('123', 123), 0); + equal(_.levenshtein(321, '321'), 0); + equal(_.levenshtein('lol', null), 3); + equal(_.levenshtein('lol'), 3); + equal(_.levenshtein(null, 'lol'), 3); + equal(_.levenshtein(undefined, 'lol'), 3); + equal(_.levenshtein(), 0); + }); + + test('Strings: ltrim', function() { + equal(_(' foo').ltrim(), 'foo'); + equal(_(' foo').ltrim(), 'foo'); + equal(_('foo ').ltrim(), 'foo '); + equal(_(' foo ').ltrim(), 'foo '); + equal(_('').ltrim(), '', 'ltrim empty string should return empty string'); + equal(_(null).ltrim(), '', 'ltrim null should return empty string'); + equal(_(undefined).ltrim(), '', 'ltrim undefined should return empty string'); + + equal(_('ffoo').ltrim('f'), 'oo'); + equal(_('ooff').ltrim('f'), 'ooff'); + equal(_('ffooff').ltrim('f'), 'ooff'); + + equal(_('_-foobar-_').ltrim('_-'), 'foobar-_'); + + equal(_(123).ltrim(1), '23'); + }); + + test('Strings: rtrim', function() { + equal(_('http://foo/').rtrim('/'), 'http://foo', 'clean trailing slash'); + equal(_(' foo').rtrim(), ' foo'); + equal(_('foo ').rtrim(), 'foo'); + equal(_('foo ').rtrim(), 'foo'); + equal(_('foo bar ').rtrim(), 'foo bar'); + equal(_(' foo ').rtrim(), ' foo'); + + equal(_('ffoo').rtrim('f'), 'ffoo'); + equal(_('ooff').rtrim('f'), 'oo'); + equal(_('ffooff').rtrim('f'), 'ffoo'); + + equal(_('_-foobar-_').rtrim('_-'), '_-foobar'); + + equal(_(123).rtrim(3), '12'); + equal(_('').rtrim(), '', 'rtrim empty string should return empty string'); + equal(_(null).rtrim(), '', 'rtrim null should return empty string'); + }); + + test('Strings: capitalize', function() { + equal(_('fabio').capitalize(), 'Fabio', 'First letter is upper case'); + equal(_.capitalize('fabio'), 'Fabio', 'First letter is upper case'); + equal(_.capitalize('FOO'), 'FOO', 'Other letters unchanged'); + equal(_(123).capitalize(), '123', 'Non string'); + equal(_.capitalize(''), '', 'Capitalizing empty string returns empty string'); + equal(_.capitalize(null), '', 'Capitalizing null returns empty string'); + equal(_.capitalize(undefined), '', 'Capitalizing undefined returns empty string'); + }); + + test('Strings: join', function() { + equal(_.join('', 'foo', 'bar'), 'foobar', 'basic join'); + equal(_.join('', 1, 'foo', 2), '1foo2', 'join numbers and strings'); + equal(_.join(' ','foo', 'bar'), 'foo bar', 'join with spaces'); + equal(_.join('1', '2', '2'), '212', 'join number strings'); + equal(_.join(1, 2, 2), '212', 'join numbers'); + equal(_.join('','foo', null), 'foo', 'join null with string returns string'); + equal(_.join(null,'foo', 'bar'), 'foobar', 'join strings with null returns string'); + equal(_(' ').join('foo', 'bar'), 'foo bar', 'join object oriented'); + }); + + test('Strings: reverse', function() { + equal(_.str.reverse('foo'), 'oof' ); + equal(_.str.reverse('foobar'), 'raboof' ); + equal(_.str.reverse('foo bar'), 'rab oof' ); + equal(_.str.reverse('saippuakauppias'), 'saippuakauppias' ); + equal(_.str.reverse(123), '321', 'Non string'); + equal(_.str.reverse(123.45), '54.321', 'Non string'); + equal(_.str.reverse(''), '', 'reversing empty string returns empty string' ); + equal(_.str.reverse(null), '', 'reversing null returns empty string' ); + equal(_.str.reverse(undefined), '', 'reversing undefined returns empty string' ); + }); + + test('Strings: clean', function() { + equal(_(' foo bar ').clean(), 'foo bar'); + equal(_(123).clean(), '123'); + equal(_('').clean(), '', 'claning empty string returns empty string'); + equal(_(null).clean(), '', 'claning null returns empty string'); + equal(_(undefined).clean(), '', 'claning undefined returns empty string'); + }); + + test('Strings: sprintf', function() { + // Should be very tested function already. Thanks to + // http://www.diveintojavascript.com/projects/sprintf-for-javascript + equal(_.sprintf('Hello %s', 'me'), 'Hello me', 'basic'); + equal(_('Hello %s').sprintf('me'), 'Hello me', 'object'); + equal(_('hello %s').chain().sprintf('me').capitalize().value(), 'Hello me', 'Chaining works'); + equal(_.sprintf('%.1f', 1.22222), '1.2', 'round'); + equal(_.sprintf('%.1f', 1.17), '1.2', 'round 2'); + equal(_.sprintf('%(id)d - %(name)s', {id: 824, name: 'Hello World'}), '824 - Hello World', 'Named replacements work'); + equal(_.sprintf('%(args[0].id)d - %(args[1].name)s', {args: [{id: 824}, {name: 'Hello World'}]}), '824 - Hello World', 'Named replacements with arrays work'); + }); + + + test('Strings: vsprintf', function() { + equal(_.vsprintf('Hello %s', ['me']), 'Hello me', 'basic'); + equal(_('Hello %s').vsprintf(['me']), 'Hello me', 'object'); + equal(_('hello %s').chain().vsprintf(['me']).capitalize().value(), 'Hello me', 'Chaining works'); + equal(_.vsprintf('%.1f', [1.22222]), '1.2', 'round'); + equal(_.vsprintf('%.1f', [1.17]), '1.2', 'round 2'); + equal(_.vsprintf('%(id)d - %(name)s', [{id: 824, name: 'Hello World'}]), '824 - Hello World', 'Named replacement works'); + equal(_.vsprintf('%(args[0].id)d - %(args[1].name)s', [{args: [{id: 824}, {name: 'Hello World'}]}]), '824 - Hello World', 'Named replacement with arrays works'); + }); + + test('Strings: startsWith', function() { + ok(_('foobar').startsWith('foo'), 'foobar starts with foo'); + ok(!_('oobar').startsWith('foo'), 'oobar does not start with foo'); + ok(_(12345).startsWith(123), '12345 starts with 123'); + ok(!_(2345).startsWith(123), '2345 does not start with 123'); + ok(_('').startsWith(''), 'empty string starts with empty string'); + ok(_(null).startsWith(''), 'null starts with empty string'); + ok(!_(null).startsWith('foo'), 'null starts with foo'); + }); + + test('Strings: endsWith', function() { + ok(_('foobar').endsWith('bar'), 'foobar ends with bar'); + ok(_.endsWith('foobar', 'bar'), 'foobar ends with bar'); + ok(_.endsWith('00018-0000062.Plone.sdh264.1a7264e6912a91aa4a81b64dc5517df7b8875994.mp4', 'mp4'), 'endsWith .mp4'); + ok(!_('fooba').endsWith('bar'), 'fooba does not end with bar'); + ok(_.endsWith(12345, 45), '12345 ends with 45'); + ok(!_.endsWith(12345, 6), '12345 does not end with 6'); + ok(_('').endsWith(''), 'empty string ends with empty string'); + ok(_(null).endsWith(''), 'null ends with empty string'); + ok(!_(null).endsWith('foo'), 'null ends with foo'); + }); + + test('Strings: include', function() { + ok(_.str.include('foobar', 'bar'), 'foobar includes bar'); + ok(!_.str.include('foobar', 'buzz'), 'foobar does not includes buzz'); + ok(_.str.include(12345, 34), '12345 includes 34'); + ok(!_.str.contains(12345, 6), '12345 does not includes 6'); + ok(!_.str.include('', 34), 'empty string includes 34'); + ok(!_.str.include(null, 34), 'null includes 34'); + ok(_.str.include(null, ''), 'null includes empty string'); + }); + + test('String: chop', function(){ + ok(_('whitespace').chop(2).length === 5, 'output [wh, it, es, pa, ce]'); + ok(_('whitespace').chop(3).length === 4, 'output [whi, tes, pac, e]'); + ok(_('whitespace').chop()[0].length === 10, 'output [whitespace]'); + ok(_(12345).chop(1).length === 5, 'output [1, 2, 3, 4, 5]'); + }); + + test('String: clean', function(){ + equal(_.clean(' foo bar '), 'foo bar'); + equal(_.clean(''), ''); + equal(_.clean(null), ''); + equal(_.clean(1), '1'); + }); + + test('String: count', function(){ + equal(_('Hello world').count('l'), 3); + equal(_('Hello world').count('Hello'), 1); + equal(_('Hello world').count('foo'), 0); + equal(_('x.xx....x.x').count('x'), 5); + equal(_('').count('x'), 0); + equal(_(null).count('x'), 0); + equal(_(undefined).count('x'), 0); + equal(_(12345).count(1), 1); + equal(_(11345).count(1), 2); + }); + + test('String: insert', function(){ + equal(_('Hello ').insert(6, 'Jessy'), 'Hello Jessy'); + equal(_('Hello ').insert(100, 'Jessy'), 'Hello Jessy'); + equal(_('').insert(100, 'Jessy'), 'Jessy'); + equal(_(null).insert(100, 'Jessy'), 'Jessy'); + equal(_(undefined).insert(100, 'Jessy'), 'Jessy'); + equal(_(12345).insert(6, 'Jessy'), '12345Jessy'); + }); + + test('String: splice', function(){ + equal(_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'), + 'https://edtsech@bitbucket.org/epeli/underscore.strings'); + equal(_.splice(12345, 1, 2, 321), '132145', 'Non strings'); + }); + + test('String: succ', function(){ + equal(_('a').succ(), 'b'); + equal(_('A').succ(), 'B'); + equal(_('+').succ(), ','); + equal(_(1).succ(), '2'); + }); + + test('String: titleize', function(){ + equal(_('the titleize string method').titleize(), 'The Titleize String Method'); + equal(_('the titleize string method').titleize(), 'The Titleize String Method'); + equal(_('').titleize(), '', 'Titleize empty string returns empty string'); + equal(_(null).titleize(), '', 'Titleize null returns empty string'); + equal(_(undefined).titleize(), '', 'Titleize undefined returns empty string'); + equal(_('let\'s have some fun').titleize(), 'Let\'s Have Some Fun'); + equal(_('a-dash-separated-string').titleize(), 'A-Dash-Separated-String'); + equal(_('A-DASH-SEPARATED-STRING').titleize(), 'A-Dash-Separated-String'); + equal(_(123).titleize(), '123'); + }); + + test('String: camelize', function(){ + equal(_('the_camelize_string_method').camelize(), 'theCamelizeStringMethod'); + equal(_('-the-camelize-string-method').camelize(), 'TheCamelizeStringMethod'); + equal(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equal(_(' the camelize string method').camelize(), 'theCamelizeStringMethod'); + equal(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equal(_('').camelize(), '', 'Camelize empty string returns empty string'); + equal(_(null).camelize(), '', 'Camelize null returns empty string'); + equal(_(undefined).camelize(), '', 'Camelize undefined returns empty string'); + equal(_(123).camelize(), '123'); + }); + + test('String: underscored', function(){ + equal(_('the-underscored-string-method').underscored(), 'the_underscored_string_method'); + equal(_('theUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equal(_('TheUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equal(_(' the underscored string method').underscored(), 'the_underscored_string_method'); + equal(_('').underscored(), ''); + equal(_(null).underscored(), ''); + equal(_(undefined).underscored(), ''); + equal(_(123).underscored(), '123'); + }); + + test('String: dasherize', function(){ + equal(_('the_dasherize_string_method').dasherize(), 'the-dasherize-string-method'); + equal(_('TheDasherizeStringMethod').dasherize(), '-the-dasherize-string-method'); + equal(_('thisIsATest').dasherize(), 'this-is-a-test'); + equal(_('this Is A Test').dasherize(), 'this-is-a-test'); + equal(_('thisIsATest123').dasherize(), 'this-is-a-test123'); + equal(_('123thisIsATest').dasherize(), '123this-is-a-test'); + equal(_('the dasherize string method').dasherize(), 'the-dasherize-string-method'); + equal(_('the dasherize string method ').dasherize(), 'the-dasherize-string-method'); + equal(_('téléphone').dasherize(), 'téléphone'); + equal(_('foo$bar').dasherize(), 'foo$bar'); + equal(_('').dasherize(), ''); + equal(_(null).dasherize(), ''); + equal(_(undefined).dasherize(), ''); + equal(_(123).dasherize(), '123'); + }); + + test('String: camelize', function(){ + equal(_.camelize('-moz-transform'), 'MozTransform'); + equal(_.camelize('webkit-transform'), 'webkitTransform'); + equal(_.camelize('under_scored'), 'underScored'); + equal(_.camelize(' with spaces'), 'withSpaces'); + equal(_('').camelize(), ''); + equal(_(null).camelize(), ''); + equal(_(undefined).camelize(), ''); + equal(_("_som eWeird---name-").camelize(), 'SomEWeirdName'); + }); + + test('String: join', function(){ + equal(_.join(1, 2, 3, 4), '21314'); + equal(_.join('|', 'foo', 'bar', 'baz'), 'foo|bar|baz'); + equal(_.join('',2,3,null), '23'); + equal(_.join(null,2,3), '23'); + }); + + test('String: classify', function(){ + equal(_.classify(1), '1'); + equal(_('some_class_name').classify(), 'SomeClassName'); + equal(_('my wonderfull class_name').classify(), 'MyWonderfullClassName'); + equal(_('my wonderfull.class.name').classify(), 'MyWonderfullClassName'); + }); + + test('String: humanize', function(){ + equal(_('the_humanize_string_method').humanize(), 'The humanize string method'); + equal(_('ThehumanizeStringMethod').humanize(), 'Thehumanize string method'); + equal(_('the humanize string method').humanize(), 'The humanize string method'); + equal(_('the humanize_id string method_id').humanize(), 'The humanize id string method'); + equal(_('the humanize string method ').humanize(), 'The humanize string method'); + equal(_(' capitalize dash-CamelCase_underscore trim ').humanize(), 'Capitalize dash camel case underscore trim'); + equal(_(123).humanize(), '123'); + equal(_('').humanize(), ''); + equal(_(null).humanize(), ''); + equal(_(undefined).humanize(), ''); + }); + + test('String: truncate', function(){ + equal(_('Hello world').truncate(6, 'read more'), 'Hello read more'); + equal(_('Hello world').truncate(5), 'Hello...'); + equal(_('Hello').truncate(10), 'Hello'); + equal(_('').truncate(10), ''); + equal(_(null).truncate(10), ''); + equal(_(undefined).truncate(10), ''); + equal(_(1234567890).truncate(5), '12345...'); + }); + + test('String: prune', function(){ + equal(_('Hello, cruel world').prune(6, ' read more'), 'Hello read more'); + equal(_('Hello, world').prune(5, 'read a lot more'), 'Hello, world'); + equal(_('Hello, world').prune(5), 'Hello...'); + equal(_('Hello, world').prune(8), 'Hello...'); + equal(_('Hello, cruel world').prune(15), 'Hello, cruel...'); + equal(_('Hello world').prune(22), 'Hello world'); + equal(_('Привет, жестокий мир').prune(6, ' read more'), 'Привет read more'); + equal(_('Привет, мир').prune(6, 'read a lot more'), 'Привет, мир'); + equal(_('Привет, мир').prune(6), 'Привет...'); + equal(_('Привет, мир').prune(8), 'Привет...'); + equal(_('Привет, жестокий мир').prune(16), 'Привет, жестокий...'); + equal(_('Привет, мир').prune(22), 'Привет, мир'); + equal(_('alksjd!!!!!!....').prune(100, ''), 'alksjd!!!!!!....'); + equal(_(123).prune(10), '123'); + equal(_(123).prune(1, 321), '321'); + equal(_('').prune(5), ''); + equal(_(null).prune(5), ''); + equal(_(undefined).prune(5), ''); + }); + + test('String: isBlank', function(){ + ok(_('').isBlank()); + ok(_(' ').isBlank()); + ok(_('\n').isBlank()); + ok(!_('a').isBlank()); + ok(!_('0').isBlank()); + ok(!_(0).isBlank()); + ok(_('').isBlank()); + ok(_(null).isBlank()); + ok(_(undefined).isBlank()); + }); + + test('String: escapeRegExp', function(){ + equal(_.escapeRegExp(/hello(?=\sworld)/.source), 'hello\\(\\?\\=\\\\sworld\\)', 'with lookahead'); + equal(_.escapeRegExp(/hello(?!\shell)/.source), 'hello\\(\\?\\!\\\\shell\\)', 'with negative lookahead'); + }); + + test('String: escapeHTML', function(){ + equal(_('
      Blah & "blah" & \'blah\'
      ').escapeHTML(), + '<div>Blah & "blah" & 'blah'</div>'); + equal(_('<').escapeHTML(), '&lt;'); + equal(_(5).escapeHTML(), '5'); + equal(_('').escapeHTML(), ''); + equal(_(null).escapeHTML(), ''); + equal(_(undefined).escapeHTML(), ''); + }); + + test('String: unescapeHTML', function(){ + equal(_('<div>Blah & "blah" & 'blah'</div>').unescapeHTML(), + '
      Blah & "blah" & \'blah\'
      '); + equal(_('&lt;').unescapeHTML(), '<'); + equal(_(''').unescapeHTML(), '\''); + equal(_(''').unescapeHTML(), '\''); + equal(_(''').unescapeHTML(), '\''); + equal(_('J').unescapeHTML(), 'J'); + equal(_('J').unescapeHTML(), 'J'); + equal(_('J').unescapeHTML(), 'J'); + equal(_('&_#39;').unescapeHTML(), '&_#39;'); + equal(_(''_;').unescapeHTML(), ''_;'); + equal(_('&#38;').unescapeHTML(), '&'); + equal(_('&amp;').unescapeHTML(), '&'); + equal(_('').unescapeHTML(), ''); + equal(_(null).unescapeHTML(), ''); + equal(_(undefined).unescapeHTML(), ''); + equal(_(5).unescapeHTML(), '5'); + // equal(_(undefined).unescapeHTML(), ''); + }); + + test('String: words', function() { + deepEqual(_('I love you!').words(), ['I', 'love', 'you!']); + deepEqual(_(' I love you! ').words(), ['I', 'love', 'you!']); + deepEqual(_('I_love_you!').words('_'), ['I', 'love', 'you!']); + deepEqual(_('I-love-you!').words(/-/), ['I', 'love', 'you!']); + deepEqual(_(123).words(), ['123'], '123 number has one word "123".'); + deepEqual(_(0).words(), ['0'], 'Zero number has one word "0".'); + deepEqual(_('').words(), [], 'Empty strings has no words.'); + deepEqual(_(' ').words(), [], 'Blank strings has no words.'); + deepEqual(_(null).words(), [], 'null has no words.'); + deepEqual(_(undefined).words(), [], 'undefined has no words.'); + }); + + test('String: chars', function() { + equal(_('Hello').chars().length, 5); + equal(_(123).chars().length, 3); + equal(_('').chars().length, 0); + equal(_(null).chars().length, 0); + equal(_(undefined).chars().length, 0); + }); + + test('String: swapCase', function(){ + equal(_('AaBbCcDdEe').swapCase(), 'aAbBcCdDeE'); + equal(_('Hello World').swapCase(), 'hELLO wORLD'); + equal(_('').swapCase(), ''); + equal(_(null).swapCase(), ''); + equal(_(undefined).swapCase(), ''); + }); + + test('String: lines', function() { + equal(_('Hello\nWorld').lines().length, 2); + equal(_('Hello World').lines().length, 1); + equal(_(123).lines().length, 1); + equal(_('').lines().length, 1); + equal(_(null).lines().length, 0); + equal(_(undefined).lines().length, 0); + }); + + test('String: pad', function() { + equal(_('1').pad(8), ' 1'); + equal(_(1).pad(8), ' 1'); + equal(_('1').pad(8, '0'), '00000001'); + equal(_('1').pad(8, '0', 'left'), '00000001'); + equal(_('1').pad(8, '0', 'right'), '10000000'); + equal(_('1').pad(8, '0', 'both'), '00001000'); + equal(_('foo').pad(8, '0', 'both'), '000foo00'); + equal(_('foo').pad(7, '0', 'both'), '00foo00'); + equal(_('foo').pad(7, '!@$%dofjrofj', 'both'), '!!foo!!'); + equal(_('').pad(2), ' '); + equal(_(null).pad(2), ' '); + equal(_(undefined).pad(2), ' '); + }); + + test('String: lpad', function() { + equal(_('1').lpad(8), ' 1'); + equal(_(1).lpad(8), ' 1'); + equal(_('1').lpad(8, '0'), '00000001'); + equal(_('1').lpad(8, '0', 'left'), '00000001'); + equal(_('').lpad(2), ' '); + equal(_(null).lpad(2), ' '); + equal(_(undefined).lpad(2), ' '); + }); + + test('String: rpad', function() { + equal(_('1').rpad(8), '1 '); + equal(_(1).lpad(8), ' 1'); + equal(_('1').rpad(8, '0'), '10000000'); + equal(_('foo').rpad(8, '0'), 'foo00000'); + equal(_('foo').rpad(7, '0'), 'foo0000'); + equal(_('').rpad(2), ' '); + equal(_(null).rpad(2), ' '); + equal(_(undefined).rpad(2), ' '); + }); + + test('String: lrpad', function() { + equal(_('1').lrpad(8), ' 1 '); + equal(_(1).lrpad(8), ' 1 '); + equal(_('1').lrpad(8, '0'), '00001000'); + equal(_('foo').lrpad(8, '0'), '000foo00'); + equal(_('foo').lrpad(7, '0'), '00foo00'); + equal(_('foo').lrpad(7, '!@$%dofjrofj'), '!!foo!!'); + equal(_('').lrpad(2), ' '); + equal(_(null).lrpad(2), ' '); + equal(_(undefined).lrpad(2), ' '); + }); + + test('String: toNumber', function() { + deepEqual(_('not a number').toNumber(), NaN); + equal(_(0).toNumber(), 0); + equal(_('0').toNumber(), 0); + equal(_('0.0').toNumber(), 0); + equal(_('0.1').toNumber(), 0); + equal(_('0.1').toNumber(1), 0.1); + equal(_(' 0.1 ').toNumber(1), 0.1); + equal(_('0000').toNumber(), 0); + equal(_('2.345').toNumber(), 2); + equal(_('2.345').toNumber(NaN), 2); + equal(_('2.345').toNumber(2), 2.35); + equal(_('2.344').toNumber(2), 2.34); + equal(_('2').toNumber(2), 2.00); + equal(_(2).toNumber(2), 2.00); + equal(_(-2).toNumber(), -2); + equal(_('-2').toNumber(), -2); + equal(_('').toNumber(), 0); + equal(_(null).toNumber(), 0); + equal(_(undefined).toNumber(), 0); + }); + + test('String: numberFormat', function() { + equal(_.numberFormat(9000), '9,000'); + equal(_.numberFormat(9000, 0), '9,000'); + equal(_.numberFormat(9000, 0, '', ''), '9000'); + equal(_.numberFormat(90000, 2), '90,000.00'); + equal(_.numberFormat(1000.754), '1,001'); + equal(_.numberFormat(1000.754, 2), '1,000.75'); + equal(_.numberFormat(1000.754, 0, ',', '.'), '1.001'); + equal(_.numberFormat(1000.754, 2, ',', '.'), '1.000,75'); + equal(_.numberFormat(1000000.754, 2, ',', '.'), '1.000.000,75'); + equal(_.numberFormat(1000000000), '1,000,000,000'); + equal(_.numberFormat(100000000), '100,000,000'); + equal(_.numberFormat('not number'), ''); + equal(_.numberFormat(), ''); + equal(_.numberFormat(null, '.', ','), ''); + equal(_.numberFormat(undefined, '.', ','), ''); + equal(_.numberFormat(new Number(5000)), '5,000'); + }); + + test('String: strRight', function() { + equal(_('This_is_a_test_string').strRight('_'), 'is_a_test_string'); + equal(_('This_is_a_test_string').strRight('string'), ''); + equal(_('This_is_a_test_string').strRight(), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strRight(''), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strRight('-'), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strRight(''), 'This_is_a_test_string'); + equal(_('').strRight('foo'), ''); + equal(_(null).strRight('foo'), ''); + equal(_(undefined).strRight('foo'), ''); + equal(_(12345).strRight(2), '345'); + }); + + test('String: strRightBack', function() { + equal(_('This_is_a_test_string').strRightBack('_'), 'string'); + equal(_('This_is_a_test_string').strRightBack('string'), ''); + equal(_('This_is_a_test_string').strRightBack(), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strRightBack(''), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strRightBack('-'), 'This_is_a_test_string'); + equal(_('').strRightBack('foo'), ''); + equal(_(null).strRightBack('foo'), ''); + equal(_(undefined).strRightBack('foo'), ''); + equal(_(12345).strRightBack(2), '345'); + }); + + test('String: strLeft', function() { + equal(_('This_is_a_test_string').strLeft('_'), 'This'); + equal(_('This_is_a_test_string').strLeft('This'), ''); + equal(_('This_is_a_test_string').strLeft(), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strLeft(''), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strLeft('-'), 'This_is_a_test_string'); + equal(_('').strLeft('foo'), ''); + equal(_(null).strLeft('foo'), ''); + equal(_(undefined).strLeft('foo'), ''); + equal(_(123454321).strLeft(3), '12'); + }); + + test('String: strLeftBack', function() { + equal(_('This_is_a_test_string').strLeftBack('_'), 'This_is_a_test'); + equal(_('This_is_a_test_string').strLeftBack('This'), ''); + equal(_('This_is_a_test_string').strLeftBack(), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strLeftBack(''), 'This_is_a_test_string'); + equal(_('This_is_a_test_string').strLeftBack('-'), 'This_is_a_test_string'); + equal(_('').strLeftBack('foo'), ''); + equal(_(null).strLeftBack('foo'), ''); + equal(_(undefined).strLeftBack('foo'), ''); + equal(_(123454321).strLeftBack(3), '123454'); + }); + + test('Strings: stripTags', function() { + equal(_('a link').stripTags(), 'a link'); + equal(_('a link + + + + + + + + +

      Underscore.string Test Suite

      +

      +

      +
        +
        +

        Underscore.string Speed Suite

        + +
        + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_standalone.html b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_standalone.html new file mode 100644 index 000000000..9854c1711 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_standalone.html @@ -0,0 +1,18 @@ + + + + Underscore.strings Test Suite + + + + + + + + +

        Underscore.string Test Suite

        +

        +

        +
          + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/arrays.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/arrays.js new file mode 100644 index 000000000..32252a3f5 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/arrays.js @@ -0,0 +1,200 @@ +$(document).ready(function() { + + module("Arrays"); + + test("first", function() { + equal(_.first([1,2,3]), 1, 'can pull out the first element of an array'); + equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); + equal(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first'); + equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first'); + equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first'); + var result = (function(){ return _.first(arguments); })(4, 3, 2, 1); + equal(result, 4, 'works on an arguments object.'); + result = _.map([[1,2,3],[1,2,3]], _.first); + equal(result.join(','), '1,1', 'works well with _.map'); + result = (function() { return _.take([1,2,3], 2); })(); + equal(result.join(','), '1,2', 'aliased as take'); + + equal(_.first(null), undefined, 'handles nulls'); + }); + + test("rest", function() { + var numbers = [1, 2, 3, 4]; + equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()'); + equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)'); + equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index'); + var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4); + equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.rest); + equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map'); + result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4); + equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object'); + }); + + test("initial", function() { + equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()'); + equal(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index'); + var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4); + equal(result.join(", "), "1, 2, 3", 'initial works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.initial); + equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map'); + }); + + test("last", function() { + equal(_.last([1,2,3]), 3, 'can pull out the last element of an array'); + equal(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last'); + equal(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last'); + equal(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last'); + var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4); + equal(result, 4, 'works on an arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.last); + equal(result.join(','), '3,3', 'works well with _.map'); + + equal(_.last(null), undefined, 'handles nulls'); + }); + + test("compact", function() { + equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); + var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3); + equal(result, 3, 'works on an arguments object'); + }); + + test("flatten", function() { + if (window.JSON) { + var list = [1, [2], [3, [[[4]]]]]; + equal(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays'); + equal(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays'); + var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); + equal(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object'); + } + }); + + test("without", function() { + var list = [1, 2, 1, 0, 3, 1, 4]; + equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object'); + var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4); + equal(result.join(', '), '2, 3, 4', 'works on an arguments object'); + + var list = [{one : 1}, {two : 2}]; + ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.'); + ok(_.without(list, list[0]).length == 1, 'ditto.'); + }); + + test("uniq", function() { + var list = [1, 2, 1, 3, 1, 4]; + equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array'); + + var list = [1, 1, 1, 2, 2, 3]; + equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster'); + + var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}]; + var iterator = function(value) { return value.name; }; + equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator'); + + var iterator = function(value) { return value +1; }; + var list = [1, 2, 2, 3, 4, 4]; + equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array'); + + var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4); + equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); + }); + + test("intersection", function() { + var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; + equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); + equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection'); + var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); + equal(result.join(''), 'moe', 'works on an arguments object'); + }); + + test("union", function() { + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); + equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); + + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); + equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays'); + }); + + test("difference", function() { + var result = _.difference([1, 2, 3], [2, 30, 40]); + equal(result.join(' '), '1 3', 'takes the difference of two arrays'); + + var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); + equal(result.join(' '), '3 4', 'takes the difference of three arrays'); + }); + + test('zip', function() { + var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; + var stooges = _.zip(names, ages, leaders); + equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths'); + }); + + test('object', function() { + var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]); + var shouldBe = {moe: 30, larry: 40, curly: 50}; + ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object'); + + result = _.object([['one', 1], ['two', 2], ['three', 3]]); + shouldBe = {one: 1, two: 2, three: 3}; + ok(_.isEqual(result, shouldBe), 'an array of pairs zipped together into an object'); + + var stooges = {moe: 30, larry: 40, curly: 50}; + ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object'); + + ok(_.isEqual(_.object(null), {}), 'handles nulls'); + }); + + test("indexOf", function() { + var numbers = [1, 2, 3]; + numbers.indexOf = null; + equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function'); + var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3); + equal(result, 1, 'works on an arguments object'); + equal(_.indexOf(null, 2), -1, 'handles nulls properly'); + + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.indexOf(numbers, num, true); + equal(index, -1, '35 is not in the list'); + + numbers = [10, 20, 30, 40, 50]; num = 40; + index = _.indexOf(numbers, num, true); + equal(index, 3, '40 is in the list'); + + numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; + index = _.indexOf(numbers, num, true); + equal(index, 1, '40 is in the list'); + + numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; + index = _.indexOf(numbers, 2, 5); + equal(index, 7, 'supports the fromIndex argument'); + }); + + test("lastIndexOf", function() { + var numbers = [1, 0, 1]; + equal(_.lastIndexOf(numbers, 1), 2); + + numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; + numbers.lastIndexOf = null; + equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); + equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); + var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0); + equal(result, 5, 'works on an arguments object'); + equal(_.indexOf(null, 2), -1, 'handles nulls properly'); + + numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; + index = _.lastIndexOf(numbers, 2, 2); + equal(index, 1, 'supports the fromIndex argument'); + }); + + test("range", function() { + equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array'); + equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); + equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); + equal(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array'); + equal(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); + equal(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); + equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); + equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs'); + }); + +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/chaining.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/chaining.js new file mode 100644 index 000000000..16cf7bf57 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/chaining.js @@ -0,0 +1,59 @@ +$(document).ready(function() { + + module("Chaining"); + + test("map/flatten/reduce", function() { + var lyrics = [ + "I'm a lumberjack and I'm okay", + "I sleep all night and I work all day", + "He's a lumberjack and he's okay", + "He sleeps all night and he works all day" + ]; + var counts = _(lyrics).chain() + .map(function(line) { return line.split(''); }) + .flatten() + .reduce(function(hash, l) { + hash[l] = hash[l] || 0; + hash[l]++; + return hash; + }, {}).value(); + ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); + }); + + test("select/reject/sortBy", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _(numbers).chain().select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("select/reject/sortBy in functional style", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _.chain(numbers).select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("reverse/concat/unshift/pop/map", function() { + var numbers = [1,2,3,4,5]; + numbers = _(numbers).chain() + .reverse() + .concat([5, 5, 5]) + .unshift(17) + .pop() + .map(function(n){ return n * 2; }) + .value(); + equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); + }); + +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/collections.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/collections.js new file mode 100644 index 000000000..e089626df --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/collections.js @@ -0,0 +1,426 @@ +$(document).ready(function() { + + module("Collections"); + + test("each", function() { + _.each([1, 2, 3], function(num, i) { + equal(num, i + 1, 'each iterators provide value and iteration count'); + }); + + var answers = []; + _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5}); + equal(answers.join(', '), '5, 10, 15', 'context object property accessed'); + + answers = []; + _.forEach([1, 2, 3], function(num){ answers.push(num); }); + equal(answers.join(', '), '1, 2, 3', 'aliased as "forEach"'); + + answers = []; + var obj = {one : 1, two : 2, three : 3}; + obj.constructor.prototype.four = 4; + _.each(obj, function(value, key){ answers.push(key); }); + equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); + delete obj.constructor.prototype.four; + + answer = null; + _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); + ok(answer, 'can reference the original collection from inside the iterator'); + + answers = 0; + _.each(null, function(){ ++answers; }); + equal(answers, 0, 'handles a null properly'); + }); + + test('map', function() { + var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); + equal(doubled.join(', '), '2, 4, 6', 'doubled numbers'); + + doubled = _.collect([1, 2, 3], function(num){ return num * 2; }); + equal(doubled.join(', '), '2, 4, 6', 'aliased as "collect"'); + + var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3}); + equal(tripled.join(', '), '3, 6, 9', 'tripled numbers with context'); + + var doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); + equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers'); + + if (document.querySelectorAll) { + var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; }); + deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.'); + } + + var ids = _.map($('#map-test').children(), function(n){ return n.id; }); + deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.'); + + var ids = _.map(document.images, function(n){ return n.id; }); + ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); + + var ifnull = _.map(null, function(){}); + ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly'); + }); + + test('reduce', function() { + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equal(sum, 6, 'can sum up an array'); + + var context = {multiplier : 3}; + sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context); + equal(sum, 18, 'can reduce with a context object'); + + sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equal(sum, 6, 'aliased as "inject"'); + + sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); + equal(sum, 6, 'OO-style reduce'); + + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }); + equal(sum, 6, 'default initial value'); + + var ifnull; + try { + _.reduce(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + }); + + test('reduceRight', function() { + var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equal(list, 'bazbarfoo', 'can perform right folds'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equal(list, 'bazbarfoo', 'aliased as "foldr"'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }); + equal(list, 'bazbarfoo', 'default initial value'); + + var ifnull; + try { + _.reduceRight(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; }); + equal(sum, 6, 'default initial value on object'); + + ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + + equal(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + + // Assert that the correct arguments are being passed. + + var args, + memo = {}, + object = {a: 1, b: 2}, + lastKey = _.keys(object).pop(); + + var expected = lastKey == 'a' + ? [memo, 1, 'a', object] + : [memo, 2, 'b', object]; + + _.reduceRight(object, function() { + args || (args = _.toArray(arguments)); + }, memo); + + deepEqual(args, expected); + + // And again, with numeric keys. + + object = {'2': 'a', '1': 'b'}; + lastKey = _.keys(object).pop(); + args = null; + + expected = lastKey == '2' + ? [memo, 'a', '2', object] + : [memo, 'b', '1', object]; + + _.reduceRight(object, function() { + args || (args = _.toArray(arguments)); + }, memo); + + deepEqual(args, expected); + }); + + test('find', function() { + var array = [1, 2, 3, 4]; + strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`'); + strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found'); + }); + + test('detect', function() { + var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; }); + equal(result, 2, 'found the first "2" and broke the loop'); + }); + + test('select', function() { + var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equal(evens.join(', '), '2, 4, 6', 'selected each even number'); + + evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"'); + }); + + test('reject', function() { + var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equal(odds.join(', '), '1, 3, 5', 'rejected each even number'); + + var context = "obj"; + + var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ + equal(context, "obj"); + return num % 2 != 0; + }, context); + equal(evens.join(', '), '2, 4, 6', 'rejected each odd number'); + }); + + test('all', function() { + ok(_.all([], _.identity), 'the empty set'); + ok(_.all([true, true, true], _.identity), 'all true values'); + ok(!_.all([true, false, true], _.identity), 'one false value'); + ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers'); + ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number'); + ok(_.all([1], _.identity) === true, 'cast to boolean - true'); + ok(_.all([0], _.identity) === false, 'cast to boolean - false'); + ok(_.every([true, true, true], _.identity), 'aliased as "every"'); + ok(!_.all([undefined, undefined, undefined], _.identity), 'works with arrays of undefined'); + }); + + test('any', function() { + var nativeSome = Array.prototype.some; + Array.prototype.some = null; + ok(!_.any([]), 'the empty set'); + ok(!_.any([false, false, false]), 'all false values'); + ok(_.any([false, false, true]), 'one true value'); + ok(_.any([null, 0, 'yes', false]), 'a string'); + ok(!_.any([null, 0, '', false]), 'falsy values'); + ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers'); + ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number'); + ok(_.any([1], _.identity) === true, 'cast to boolean - true'); + ok(_.any([0], _.identity) === false, 'cast to boolean - false'); + ok(_.some([false, false, true]), 'aliased as "some"'); + Array.prototype.some = nativeSome; + }); + + test('include', function() { + ok(_.include([1,2,3], 2), 'two is in the array'); + ok(!_.include([1,3,9], 2), 'two is not in the array'); + ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values'); + ok(_([1,2,3]).include(2), 'OO-style include'); + }); + + test('invoke', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, 'sort'); + equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + test('invoke w/ function reference', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, Array.prototype.sort); + equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + // Relevant when using ClojureScript + test('invoke when strings have a call method', function() { + String.prototype.call = function() { + return 42; + }; + var list = [[5, 1, 7], [3, 2, 1]]; + var s = "foo"; + equal(s.call(), 42, "call function exists"); + var result = _.invoke(list, 'sort'); + equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); + delete String.prototype.call; + equal(s.call, undefined, "call function removed"); + }); + + test('pluck', function() { + var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; + equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); + }); + + test('where', function() { + var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; + var result = _.where(list, {a: 1}); + equal(result.length, 3); + equal(result[result.length - 1].b, 4); + result = _.where(list, {b: 2}); + equal(result.length, 2); + equal(result[0].a, 1); + }); + + test('max', function() { + equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); + + var neg = _.max([1, 2, 3], function(num){ return -num; }); + equal(neg, 1, 'can perform a computation-based max'); + + equal(-Infinity, _.max({}), 'Maximum value of an empty object'); + equal(-Infinity, _.max([]), 'Maximum value of an empty array'); + + equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array"); + }); + + test('min', function() { + equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); + + var neg = _.min([1, 2, 3], function(num){ return -num; }); + equal(neg, 3, 'can perform a computation-based min'); + + equal(Infinity, _.min({}), 'Minimum value of an empty object'); + equal(Infinity, _.min([]), 'Minimum value of an empty array'); + + var now = new Date(9999999999); + var then = new Date(0); + equal(_.min([now, then]), then); + + equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array"); + }); + + test('sortBy', function() { + var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; + people = _.sortBy(people, function(person){ return person.age; }); + equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age'); + + var list = [undefined, 4, 1, undefined, 3, 2]; + equal(_.sortBy(list, _.identity).join(','), '1,2,3,4,,', 'sortBy with undefined values'); + + var list = ["one", "two", "three", "four", "five"]; + var sorted = _.sortBy(list, 'length'); + equal(sorted.join(' '), 'one two four five three', 'sorted by length'); + + function Pair(x, y) { + this.x = x; + this.y = y; + } + + var collection = [ + new Pair(1, 1), new Pair(1, 2), + new Pair(1, 3), new Pair(1, 4), + new Pair(1, 5), new Pair(1, 6), + new Pair(2, 1), new Pair(2, 2), + new Pair(2, 3), new Pair(2, 4), + new Pair(2, 5), new Pair(2, 6), + new Pair(undefined, 1), new Pair(undefined, 2), + new Pair(undefined, 3), new Pair(undefined, 4), + new Pair(undefined, 5), new Pair(undefined, 6) + ]; + + var actual = _.sortBy(collection, function(pair) { + return pair.x; + }); + + deepEqual(actual, collection, 'sortBy should be stable'); + }); + + test('groupBy', function() { + var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); + ok('0' in parity && '1' in parity, 'created a group for each value'); + equal(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group'); + + var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; + var grouped = _.groupBy(list, 'length'); + equal(grouped['3'].join(' '), 'one two six ten'); + equal(grouped['4'].join(' '), 'four five nine'); + equal(grouped['5'].join(' '), 'three seven eight'); + + var context = {}; + _.groupBy([{}], function(){ ok(this === context); }, context); + + grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { + return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; + }); + equal(grouped.constructor.length, 1); + equal(grouped.hasOwnProperty.length, 2); + + var array = [{}]; + _.groupBy(array, function(value, index, obj){ ok(obj === array); }); + }); + + test('countBy', function() { + var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; }); + equal(parity['true'], 2); + equal(parity['false'], 3); + + var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; + var grouped = _.countBy(list, 'length'); + equal(grouped['3'], 4); + equal(grouped['4'], 3); + equal(grouped['5'], 3); + + var context = {}; + _.countBy([{}], function(){ ok(this === context); }, context); + + grouped = _.countBy([4.2, 6.1, 6.4], function(num) { + return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; + }); + equal(grouped.constructor, 1); + equal(grouped.hasOwnProperty, 2); + + var array = [{}]; + _.countBy(array, function(value, index, obj){ ok(obj === array); }); + }); + + test('sortedIndex', function() { + var numbers = [10, 20, 30, 40, 50], num = 35; + var indexForNum = _.sortedIndex(numbers, num); + equal(indexForNum, 3, '35 should be inserted at index 3'); + + var indexFor30 = _.sortedIndex(numbers, 30); + equal(indexFor30, 2, '30 should be inserted at index 2'); + + var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}]; + var iterator = function(obj){ return obj.x; }; + strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2); + strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3); + + var context = {1: 2, 2: 3, 3: 4}; + iterator = function(obj){ return this[obj]; }; + strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1); + }); + + test('shuffle', function() { + var numbers = _.range(10); + var shuffled = _.shuffle(numbers).sort(); + notStrictEqual(numbers, shuffled, 'original object is unmodified'); + equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle'); + }); + + test('toArray', function() { + ok(!_.isArray(arguments), 'arguments object is not an array'); + ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); + var a = [1,2,3]; + ok(_.toArray(a) !== a, 'array is cloned'); + equal(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements'); + + var numbers = _.toArray({one : 1, two : 2, three : 3}); + equal(numbers.join(', '), '1, 2, 3', 'object flattened into array'); + }); + + test('size', function() { + equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); + equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); + + var func = function() { + return _.size(arguments); + }; + + equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); + + equal(_.size('hello'), 5, 'can compute the size of a string'); + + equal(_.size(null), 0, 'handles nulls'); + }); + +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/functions.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/functions.js new file mode 100644 index 000000000..a52965877 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/functions.js @@ -0,0 +1,259 @@ +$(document).ready(function() { + + module("Functions"); + + test("bind", function() { + var context = {name : 'moe'}; + var func = function(arg) { return "name: " + (this.name || arg); }; + var bound = _.bind(func, context); + equal(bound(), 'name: moe', 'can bind a function to a context'); + + bound = _(func).bind(context); + equal(bound(), 'name: moe', 'can do OO-style binding'); + + bound = _.bind(func, null, 'curly'); + equal(bound(), 'name: curly', 'can bind without specifying a context'); + + func = function(salutation, name) { return salutation + ': ' + name; }; + func = _.bind(func, this, 'hello'); + equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); + + var func = _.bind(func, this, 'curly'); + equal(func(), 'hello: curly', 'the function was completely applied in advance'); + + var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; + func = _.bind(func, this, 'hello', 'moe', 'curly'); + equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); + + func = function(context, message) { equal(this, context, message); }; + _.bind(func, 0, 0, 'can bind a function to `0`')(); + _.bind(func, '', '', 'can bind a function to an empty string')(); + _.bind(func, false, false, 'can bind a function to `false`')(); + + // These tests are only meaningful when using a browser without a native bind function + // To test this with a modern browser, set underscore's nativeBind to undefined + var F = function () { return this; }; + var Boundf = _.bind(F, {hello: "moe curly"}); + equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5"); + equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); + }); + + test("bindAll", function() { + var curly = {name : 'curly'}, moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + curly.getName = moe.getName; + _.bindAll(moe, 'getName', 'sayHi'); + curly.sayHi = moe.sayHi; + equal(curly.getName(), 'name: curly', 'unbound function is bound to current object'); + equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); + + curly = {name : 'curly'}; + moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + _.bindAll(moe); + curly.sayHi = moe.sayHi; + equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object'); + }); + + test("memoize", function() { + var fib = function(n) { + return n < 2 ? n : fib(n - 1) + fib(n - 2); + }; + var fastFib = _.memoize(fib); + equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); + equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results'); + + var o = function(str) { + return str; + }; + var fastO = _.memoize(o); + equal(o('toString'), 'toString', 'checks hasOwnProperty'); + equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); + }); + + asyncTest("delay", 2, function() { + var delayed = false; + _.delay(function(){ delayed = true; }, 100); + setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50); + setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150); + }); + + asyncTest("defer", 1, function() { + var deferred = false; + _.defer(function(bool){ deferred = bool; }, true); + _.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50); + }); + + asyncTest("throttle", 2, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); throttledIncr(); + setTimeout(throttledIncr, 70); + setTimeout(throttledIncr, 120); + setTimeout(throttledIncr, 140); + setTimeout(throttledIncr, 190); + setTimeout(throttledIncr, 220); + setTimeout(throttledIncr, 240); + _.delay(function(){ equal(counter, 1, "incr was called immediately"); }, 30); + _.delay(function(){ equal(counter, 4, "incr was throttled"); start(); }, 400); + }); + + asyncTest("throttle arguments", 2, function() { + var value = 0; + var update = function(val){ value = val; }; + var throttledUpdate = _.throttle(update, 100); + throttledUpdate(1); throttledUpdate(2); throttledUpdate(3); + setTimeout(function(){ throttledUpdate(4); }, 120); + setTimeout(function(){ throttledUpdate(5); }, 140); + setTimeout(function(){ throttledUpdate(6); }, 250); + _.delay(function(){ equal(value, 1, "updated to latest value"); }, 40); + _.delay(function(){ equal(value, 6, "updated to latest value"); start(); }, 400); + }); + + asyncTest("throttle once", 2, function() { + var counter = 0; + var incr = function(){ return ++counter; }; + var throttledIncr = _.throttle(incr, 100); + var result = throttledIncr(); + _.delay(function(){ + equal(result, 1, "throttled functions return their value"); + equal(counter, 1, "incr was called once"); start(); + }, 220); + }); + + asyncTest("throttle twice", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); + _.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 220); + }); + + asyncTest("throttle repeatedly with results", 9, function() { + var counter = 0; + var incr = function(){ return ++counter; }; + var throttledIncr = _.throttle(incr, 100); + var results = []; + var saveResult = function() { results.push(throttledIncr()); }; + saveResult(); saveResult(); saveResult(); + setTimeout(saveResult, 70); + setTimeout(saveResult, 120); + setTimeout(saveResult, 140); + setTimeout(saveResult, 190); + setTimeout(saveResult, 240); + setTimeout(saveResult, 260); + _.delay(function() { + equal(results[0], 1, "incr was called once"); + equal(results[1], 1, "incr was throttled"); + equal(results[2], 1, "incr was throttled"); + equal(results[3], 1, "incr was throttled"); + equal(results[4], 2, "incr was called twice"); + equal(results[5], 2, "incr was throttled"); + equal(results[6], 2, "incr was throttled"); + equal(results[7], 3, "incr was called thrice"); + equal(results[8], 3, "incr was throttled"); + start(); + }, 400); + }); + + asyncTest("debounce", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var debouncedIncr = _.debounce(incr, 50); + debouncedIncr(); debouncedIncr(); debouncedIncr(); + setTimeout(debouncedIncr, 30); + setTimeout(debouncedIncr, 60); + setTimeout(debouncedIncr, 90); + setTimeout(debouncedIncr, 120); + setTimeout(debouncedIncr, 150); + _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220); + }); + + asyncTest("debounce asap", 5, function() { + var a, b, c; + var counter = 0; + var incr = function(){ return ++counter; }; + var debouncedIncr = _.debounce(incr, 50, true); + a = debouncedIncr(); + b = debouncedIncr(); + c = debouncedIncr(); + equal(a, 1); + equal(b, 1); + equal(c, 1); + equal(counter, 1, 'incr was called immediately'); + setTimeout(debouncedIncr, 30); + setTimeout(debouncedIncr, 60); + setTimeout(debouncedIncr, 90); + setTimeout(debouncedIncr, 120); + setTimeout(debouncedIncr, 150); + _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220); + }); + + asyncTest("debounce asap recursively", 2, function() { + var counter = 0; + var debouncedIncr = _.debounce(function(){ + counter++; + if (counter < 5) debouncedIncr(); + }, 50, true); + debouncedIncr(); + equal(counter, 1, 'incr was called immediately'); + _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 70); + }); + + test("once", function() { + var num = 0; + var increment = _.once(function(){ num++; }); + increment(); + increment(); + equal(num, 1); + }); + + test("wrap", function() { + var greet = function(name){ return "hi: " + name; }; + var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); + equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function'); + + var inner = function(){ return "Hello "; }; + var obj = {name : "Moe"}; + obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); + equal(obj.hi(), "Hello Moe"); + + var noop = function(){}; + var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); }); + var ret = wrapped(['whats', 'your'], 'vector', 'victor'); + deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); + }); + + test("compose", function() { + var greet = function(name){ return "hi: " + name; }; + var exclaim = function(sentence){ return sentence + '!'; }; + var composed = _.compose(exclaim, greet); + equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); + + composed = _.compose(greet, exclaim); + equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); + }); + + test("after", function() { + var testAfter = function(afterAmount, timesCalled) { + var afterCalled = 0; + var after = _.after(afterAmount, function() { + afterCalled++; + }); + while (timesCalled--) after(); + return afterCalled; + }; + + equal(testAfter(5, 5), 1, "after(N) should fire after being called N times"); + equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times"); + equal(testAfter(0, 0), 1, "after(0) should fire immediately"); + }); + +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/index.html b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/index.html new file mode 100644 index 000000000..064fa9861 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/index.html @@ -0,0 +1,45 @@ + + + + Underscore Test Suite + + + + + + + + + + + + + + + + +
          +
          +
          +
          +
          +
          +
          +
          +

          Underscore Speed Suite

          +

          + A representative sample of the functions are benchmarked here, to provide + a sense of how fast they might run in different browsers. + Each iteration runs on an array of 1000 elements.

          + For example, the 'intersection' test measures the number of times you can + find the intersection of two thousand-element arrays in one second. +

          +
          + + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/objects.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/objects.js new file mode 100644 index 000000000..22949c3bf --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/objects.js @@ -0,0 +1,548 @@ +$(document).ready(function() { + + module("Objects"); + + test("keys", function() { + equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); + // the test above is not safe because it relies on for-in enumeration order + var a = []; a[1] = 0; + equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95'); + raises(function() { _.keys(null); }, TypeError, 'throws an error for `null` values'); + raises(function() { _.keys(void 0); }, TypeError, 'throws an error for `undefined` values'); + raises(function() { _.keys(1); }, TypeError, 'throws an error for number primitives'); + raises(function() { _.keys('a'); }, TypeError, 'throws an error for string primitives'); + raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives'); + }); + + test("values", function() { + equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object'); + equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"'); + }); + + test("pairs", function() { + deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); + deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); + }); + + test("invert", function() { + var obj = {first: 'Moe', second: 'Larry', third: 'Curly'}; + equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object'); + ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started'); + + var obj = {length: 3}; + ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"') + }); + + test("functions", function() { + var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; + ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); + + var Animal = function(){}; + Animal.prototype.run = function(){}; + equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype'); + }); + + test("extend", function() { + var result; + equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another'); + equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination'); + equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden'); + result = _.extend({x:'x'}, {a:'a'}, {b:'b'}); + ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects'); + result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'}); + ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); + result = _.extend({}, {a: void 0, b: null}); + equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); + }); + + test("pick", function() { + var result; + result = _.pick({a:1, b:2, c:3}, 'a', 'c'); + ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named'); + result = _.pick({a:1, b:2, c:3}, ['b', 'c']); + ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array'); + result = _.pick({a:1, b:2, c:3}, ['a'], 'b'); + ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args'); + + var Obj = function(){}; + Obj.prototype = {a: 1, b: 2, c: 3}; + ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props'); + }); + + test("omit", function() { + var result; + result = _.omit({a:1, b:2, c:3}, 'b'); + ok(_.isEqual(result, {a:1, c:3}), 'can omit a single named property'); + result = _.omit({a:1, b:2, c:3}, 'a', 'c'); + ok(_.isEqual(result, {b:2}), 'can omit several named properties'); + result = _.omit({a:1, b:2, c:3}, ['b', 'c']); + ok(_.isEqual(result, {a:1}), 'can omit properties named in an array'); + + var Obj = function(){}; + Obj.prototype = {a: 1, b: 2, c: 3}; + ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props'); + }); + + test("defaults", function() { + var result; + var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"}; + + _.defaults(options, {zero: 1, one: 10, twenty: 20}); + equal(options.zero, 0, 'value exists'); + equal(options.one, 1, 'value exists'); + equal(options.twenty, 20, 'default applied'); + + _.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"}); + equal(options.empty, "", 'value exists'); + ok(_.isNaN(options.nan), "NaN isn't overridden"); + equal(options.word, "word", 'new value is added, first one wins'); + }); + + test("clone", function() { + var moe = {name : 'moe', lucky : [13, 27, 34]}; + var clone = _.clone(moe); + equal(clone.name, 'moe', 'the clone as the attributes of the original'); + + clone.name = 'curly'; + ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original'); + + clone.lucky.push(101); + equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); + + equal(_.clone(undefined), void 0, 'non objects should not be changed by clone'); + equal(_.clone(1), 1, 'non objects should not be changed by clone'); + equal(_.clone(null), null, 'non objects should not be changed by clone'); + }); + + test("isEqual", function() { + function First() { + this.value = 1; + } + First.prototype.value = 1; + function Second() { + this.value = 1; + } + Second.prototype.value = 2; + + // Basic equality and identity comparisons. + ok(_.isEqual(null, null), "`null` is equal to `null`"); + ok(_.isEqual(), "`undefined` is equal to `undefined`"); + + ok(!_.isEqual(0, -0), "`0` is not equal to `-0`"); + ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`"); + ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`"); + ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`"); + + // String object and primitive comparisons. + ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal"); + ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal"); + ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal"); + ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives"); + + ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal"); + ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal"); + ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal"); + + // Number object and primitive comparisons. + ok(_.isEqual(75, 75), "Identical number primitives are equal"); + ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal"); + ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives"); + ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal"); + ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`"); + + ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal"); + ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal"); + + // Comparisons involving `NaN`. + ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`"); + ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`"); + ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`"); + ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`"); + + // Boolean object and primitive comparisons. + ok(_.isEqual(true, true), "Identical boolean primitives are equal"); + ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal"); + ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans"); + ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal"); + + // Common type coercions. + ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`"); + ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal"); + ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal"); + ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values"); + ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal"); + ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal"); + ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal"); + ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal"); + ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal"); + + // Dates. + ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal"); + ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal"); + ok(!_.isEqual(new Date(2009, 11, 13), { + getTime: function(){ + return 12606876e5; + } + }), "Date objects and objects with a `getTime` method are not equal"); + ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal"); + + // Functions. + ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal"); + + // RegExps. + ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal"); + ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal"); + ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal"); + ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps"); + ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal"); + + // Empty arrays, array-like objects, and object literals. + ok(_.isEqual({}, {}), "Empty object literals are equal"); + ok(_.isEqual([], []), "Empty array literals are equal"); + ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal"); + ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal."); + ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects"); + + ok(!_.isEqual({}, []), "Object literals and array literals are not equal"); + ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays"); + + // Arrays with primitive and object values. + ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal"); + ok(_.isEqual([(/Moe/g), new Date(2009, 9, 25)], [(/Moe/g), new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal"); + + // Multi-dimensional arrays. + var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared"); + + // Overwrite the methods defined in ES 5.1 section 15.4.4. + a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; + b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; + + // Array elements and properties. + ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal"); + a.push("White Rocks"); + ok(!_.isEqual(a, b), "Arrays of different lengths are not equal"); + a.push("East Boulder"); + b.push("Gunbarrel Ranch", "Teller Farm"); + ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal"); + + // Sparse arrays. + ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal"); + ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty"); + + // Simple objects. + ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal"); + ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal"); + ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal"); + ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects"); + ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent"); + + // `A` contains nested objects and arrays. + a = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + + // `B` contains equivalent nested objects and arrays. + b = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared"); + + // Instances. + ok(_.isEqual(new First, new First), "Object instances are equal"); + ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal"); + ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal"); + ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined"); + + // Circular Arrays. + (a = []).push(a); + (b = []).push(b); + ok(_.isEqual(a, b), "Arrays containing circular references are equal"); + a.push(new String("Larry")); + b.push(new String("Larry")); + ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal"); + a.push("Shemp"); + b.push("Curly"); + ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal"); + + // More circular arrays #767. + a = ["everything is checked but", "this", "is not"]; + a[1] = a; + b = ["everything is checked but", ["this", "array"], "is not"]; + ok(!_.isEqual(a, b), "Comparison of circular references with non-circular references are not equal"); + + // Circular Objects. + a = {abc: null}; + b = {abc: null}; + a.abc = a; + b.abc = b; + ok(_.isEqual(a, b), "Objects containing circular references are equal"); + a.def = 75; + b.def = 75; + ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal"); + a.def = new Number(75); + b.def = new Number(63); + ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal"); + + // More circular objects #767. + a = {everything: "is checked", but: "this", is: "not"}; + a.but = a; + b = {everything: "is checked", but: {that:"object"}, is: "not"}; + ok(!_.isEqual(a, b), "Comparison of circular references with non-circular object references are not equal"); + + // Cyclic Structures. + a = [{abc: null}]; + b = [{abc: null}]; + (a[0].abc = a).push(a); + (b[0].abc = b).push(b); + ok(_.isEqual(a, b), "Cyclic structures are equal"); + a[0].def = "Larry"; + b[0].def = "Larry"; + ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal"); + a[0].def = new String("Larry"); + b[0].def = new String("Curly"); + ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal"); + + // Complex Circular References. + a = {foo: {b: {foo: {c: {foo: null}}}}}; + b = {foo: {b: {foo: {c: {foo: null}}}}}; + a.foo.b.foo.c.foo = a; + b.foo.b.foo.c.foo = b; + ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal"); + + // Chaining. + ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); + equal(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained'); + + // Custom `isEqual` methods. + var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}}; + var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}}; + + ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods'); + ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods'); + ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal'); + ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods'); + + // Objects from another frame. + ok(_.isEqual({}, iObject)); + }); + + test("isEmpty", function() { + ok(!_([1]).isEmpty(), '[1] is not empty'); + ok(_.isEmpty([]), '[] is empty'); + ok(!_.isEmpty({one : 1}), '{one : 1} is not empty'); + ok(_.isEmpty({}), '{} is empty'); + ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); + ok(_.isEmpty(null), 'null is empty'); + ok(_.isEmpty(), 'undefined is empty'); + ok(_.isEmpty(''), 'the empty string is empty'); + ok(!_.isEmpty('moe'), 'but other strings are not'); + + var obj = {one : 1}; + delete obj.one; + ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); + }); + + // Setup remote variables for iFrame tests. + var iframe = document.createElement('iframe'); + jQuery(iframe).appendTo(document.body); + var iDoc = iframe.contentDocument || iframe.contentWindow.document; + iDoc.write( + "" + ); + iDoc.close(); + + test("isElement", function() { + ok(!_.isElement('div'), 'strings are not dom elements'); + ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); + ok(_.isElement(iElement), 'even from another frame'); + }); + + test("isArguments", function() { + var args = (function(){ return arguments; })(1, 2, 3); + ok(!_.isArguments('string'), 'a string is not an arguments object'); + ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); + ok(_.isArguments(args), 'but the arguments object is an arguments object'); + ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); + ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.'); + ok(_.isArguments(iArguments), 'even from another frame'); + }); + + test("isObject", function() { + ok(_.isObject(arguments), 'the arguments object is object'); + ok(_.isObject([1, 2, 3]), 'and arrays'); + ok(_.isObject($('html')[0]), 'and DOM element'); + ok(_.isObject(iElement), 'even from another frame'); + ok(_.isObject(function () {}), 'and functions'); + ok(_.isObject(iFunction), 'even from another frame'); + ok(!_.isObject(null), 'but not null'); + ok(!_.isObject(undefined), 'and not undefined'); + ok(!_.isObject('string'), 'and not string'); + ok(!_.isObject(12), 'and not number'); + ok(!_.isObject(true), 'and not boolean'); + ok(_.isObject(new String('string')), 'but new String()'); + }); + + test("isArray", function() { + ok(!_.isArray(arguments), 'the arguments object is not an array'); + ok(_.isArray([1, 2, 3]), 'but arrays are'); + ok(_.isArray(iArray), 'even from another frame'); + }); + + test("isString", function() { + ok(!_.isString(document.body), 'the document body is not a string'); + ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); + ok(_.isString(iString), 'even from another frame'); + }); + + test("isNumber", function() { + ok(!_.isNumber('string'), 'a string is not a number'); + ok(!_.isNumber(arguments), 'the arguments object is not a number'); + ok(!_.isNumber(undefined), 'undefined is not a number'); + ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); + ok(_.isNumber(NaN), 'NaN *is* a number'); + ok(_.isNumber(Infinity), 'Infinity is a number'); + ok(_.isNumber(iNumber), 'even from another frame'); + ok(!_.isNumber('1'), 'numeric strings are not numbers'); + }); + + test("isBoolean", function() { + ok(!_.isBoolean(2), 'a number is not a boolean'); + ok(!_.isBoolean("string"), 'a string is not a boolean'); + ok(!_.isBoolean("false"), 'the string "false" is not a boolean'); + ok(!_.isBoolean("true"), 'the string "true" is not a boolean'); + ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); + ok(!_.isBoolean(undefined), 'undefined is not a boolean'); + ok(!_.isBoolean(NaN), 'NaN is not a boolean'); + ok(!_.isBoolean(null), 'null is not a boolean'); + ok(_.isBoolean(true), 'but true is'); + ok(_.isBoolean(false), 'and so is false'); + ok(_.isBoolean(iBoolean), 'even from another frame'); + }); + + test("isFunction", function() { + ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); + ok(!_.isFunction('moe'), 'strings are not functions'); + ok(_.isFunction(_.isFunction), 'but functions are'); + ok(_.isFunction(iFunction), 'even from another frame'); + }); + + test("isDate", function() { + ok(!_.isDate(100), 'numbers are not dates'); + ok(!_.isDate({}), 'objects are not dates'); + ok(_.isDate(new Date()), 'but dates are'); + ok(_.isDate(iDate), 'even from another frame'); + }); + + test("isRegExp", function() { + ok(!_.isRegExp(_.identity), 'functions are not RegExps'); + ok(_.isRegExp(/identity/), 'but RegExps are'); + ok(_.isRegExp(iRegExp), 'even from another frame'); + }); + + test("isFinite", function() { + ok(!_.isFinite(undefined), 'undefined is not Finite'); + ok(!_.isFinite(null), 'null is not Finite'); + ok(!_.isFinite(NaN), 'NaN is not Finite'); + ok(!_.isFinite(Infinity), 'Infinity is not Finite'); + ok(!_.isFinite(-Infinity), '-Infinity is not Finite'); + ok(!_.isFinite('12'), 'Strings are not numbers'); + var obj = new Number(5); + ok(_.isFinite(obj), 'Number instances can be finite'); + ok(_.isFinite(0), '0 is Finite'); + ok(_.isFinite(123), 'Ints are Finite'); + ok(_.isFinite(-12.44), 'Floats are Finite'); + }); + + test("isNaN", function() { + ok(!_.isNaN(undefined), 'undefined is not NaN'); + ok(!_.isNaN(null), 'null is not NaN'); + ok(!_.isNaN(0), '0 is not NaN'); + ok(_.isNaN(NaN), 'but NaN is'); + ok(_.isNaN(iNaN), 'even from another frame'); + ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); + }); + + test("isNull", function() { + ok(!_.isNull(undefined), 'undefined is not null'); + ok(!_.isNull(NaN), 'NaN is not null'); + ok(_.isNull(null), 'but null is'); + ok(_.isNull(iNull), 'even from another frame'); + }); + + test("isUndefined", function() { + ok(!_.isUndefined(1), 'numbers are defined'); + ok(!_.isUndefined(null), 'null is defined'); + ok(!_.isUndefined(false), 'false is defined'); + ok(!_.isUndefined(NaN), 'NaN is defined'); + ok(_.isUndefined(), 'nothing is undefined'); + ok(_.isUndefined(undefined), 'undefined is undefined'); + ok(_.isUndefined(iUndefined), 'even from another frame'); + }); + + if (window.ActiveXObject) { + test("IE host objects", function() { + var xml = new ActiveXObject("Msxml2.DOMDocument.3.0"); + ok(!_.isNumber(xml)); + ok(!_.isBoolean(xml)); + ok(!_.isNaN(xml)); + ok(!_.isFunction(xml)); + ok(!_.isNull(xml)); + ok(!_.isUndefined(xml)); + }); + } + + test("tap", function() { + var intercepted = null; + var interceptor = function(obj) { intercepted = obj; }; + var returned = _.tap(1, interceptor); + equal(intercepted, 1, "passes tapped object to interceptor"); + equal(returned, 1, "returns tapped object"); + + returned = _([1,2,3]).chain(). + map(function(n){ return n * 2; }). + max(). + tap(interceptor). + value(); + ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); + }); +}); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/speed.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/speed.js new file mode 100644 index 000000000..05e3f2a37 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/speed.js @@ -0,0 +1,75 @@ +(function() { + + var numbers = []; + for (var i=0; i<1000; i++) numbers.push(i); + var objects = _.map(numbers, function(n){ return {num : n}; }); + var randomized = _.sortBy(numbers, function(){ return Math.random(); }); + var deep = _.map(_.range(100), function() { return _.range(1000); }); + + JSLitmus.test('_.each()', function() { + var timesTwo = []; + _.each(numbers, function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('_(list).each()', function() { + var timesTwo = []; + _(numbers).each(function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('jQuery.each()', function() { + var timesTwo = []; + jQuery.each(numbers, function(){ timesTwo.push(this * 2); }); + return timesTwo; + }); + + JSLitmus.test('_.map()', function() { + return _.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('jQuery.map()', function() { + return jQuery.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('_.pluck()', function() { + return _.pluck(objects, 'num'); + }); + + JSLitmus.test('_.uniq()', function() { + return _.uniq(randomized); + }); + + JSLitmus.test('_.uniq() (sorted)', function() { + return _.uniq(numbers, true); + }); + + JSLitmus.test('_.sortBy()', function() { + return _.sortBy(numbers, function(num){ return -num; }); + }); + + JSLitmus.test('_.isEqual()', function() { + return _.isEqual(numbers, randomized); + }); + + JSLitmus.test('_.keys()', function() { + return _.keys(objects); + }); + + JSLitmus.test('_.values()', function() { + return _.values(objects); + }); + + JSLitmus.test('_.intersection()', function() { + return _.intersection(numbers, randomized); + }); + + JSLitmus.test('_.range()', function() { + return _.range(1000); + }); + + JSLitmus.test('_.flatten()', function() { + return _.flatten(deep); + }); + +})(); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/utility.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/utility.js new file mode 100644 index 000000000..c9be20ad7 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore.string/test/test_underscore/utility.js @@ -0,0 +1,249 @@ +$(document).ready(function() { + + var templateSettings; + + module("Utility", { + + setup: function() { + templateSettings = _.clone(_.templateSettings); + }, + + teardown: function() { + _.templateSettings = templateSettings; + } + + }); + + test("#750 - Return _ instance.", 2, function() { + var instance = _([]); + ok(_(instance) === instance); + ok(new _(instance) === instance); + }); + + test("identity", function() { + var moe = {name : 'moe'}; + equal(_.identity(moe), moe, 'moe is the same as his identity'); + }); + + test("uniqueId", function() { + var ids = [], i = 0; + while(i++ < 100) ids.push(_.uniqueId()); + equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); + }); + + test("times", function() { + var vals = []; + _.times(3, function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); + // + vals = []; + _(3).times(function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); + }); + + test("mixin", function() { + _.mixin({ + myReverse: function(string) { + return string.split('').reverse().join(''); + } + }); + equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); + equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); + }); + + test("_.escape", function() { + equal(_.escape("Curly & Moe"), "Curly & Moe"); + equal(_.escape("Curly & Moe"), "Curly &amp; Moe"); + equal(_.escape(null), ''); + }); + + test("_.unescape", function() { + var string = "Curly & Moe"; + equal(_.unescape("Curly & Moe"), string); + equal(_.unescape("Curly &amp; Moe"), "Curly & Moe"); + equal(_.unescape(null), ''); + equal(_.unescape(_.escape(string)), string); + }); + + test("template", function() { + var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); + var result = basicTemplate({thing : 'This'}); + equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); + + var sansSemicolonTemplate = _.template("A <% this %> B"); + equal(sansSemicolonTemplate(), "A B"); + + var backslashTemplate = _.template("<%= thing %> is \\ridanculous"); + equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous"); + + var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); + equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); + + var fancyTemplate = _.template("
            <% \ + for (key in people) { \ + %>
          • <%= people[key] %>
          • <% } %>
          "); + result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); + equal(result, "
          • Moe
          • Larry
          • Curly
          ", 'can run arbitrary javascript in templates'); + + var escapedCharsInJavascriptTemplate = _.template("
            <% _.each(numbers.split('\\n'), function(item) { %>
          • <%= item %>
          • <% }) %>
          "); + result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); + equal(result, "
          • one
          • two
          • three
          • four
          ", 'Can use escaped characters (e.g. \\n) in Javascript'); + + var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
          \">
          <% }); %>"); + result = namespaceCollisionTemplate({ + pageCount: 3, + thumbnails: { + 1: "p1-thumbnail.gif", + 2: "p2-thumbnail.gif", + 3: "p3-thumbnail.gif" + } + }); + equal(result, "3 p3-thumbnail.gif
          "); + + var noInterpolateTemplate = _.template("

          Just some text. Hey, I know this is silly but it aids consistency.

          "); + result = noInterpolateTemplate(); + equal(result, "

          Just some text. Hey, I know this is silly but it aids consistency.

          "); + + var quoteTemplate = _.template("It's its, not it's"); + equal(quoteTemplate({}), "It's its, not it's"); + + var quoteInStatementAndBody = _.template("<%\ + if(foo == 'bar'){ \ + %>Statement quotes and 'quotes'.<% } %>"); + equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'."); + + var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); + equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); + + var template = _.template("<%- value %>"); + var result = template({value: " + + + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/index.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/index.js new file mode 100644 index 000000000..2cf0ca5b0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/package.json b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/package.json new file mode 100644 index 000000000..fac3851c0 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/package.json @@ -0,0 +1,39 @@ +{ + "name": "underscore", + "description": "JavaScript's functional programming helper library.", + "homepage": "http://underscorejs.org", + "keywords": [ + "util", + "functional", + "server", + "client", + "browser" + ], + "author": { + "name": "Jeremy Ashkenas", + "email": "jeremy@documentcloud.org" + }, + "repository": { + "type": "git", + "url": "git://github.com/documentcloud/underscore.git" + }, + "main": "underscore.js", + "version": "1.4.4", + "devDependencies": { + "phantomjs": "0.2.2" + }, + "scripts": { + "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true" + }, + "readme": " __\n /\\ \\ __\n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____\n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\\n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n \\ \\____/\n \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/documentcloud/underscore/issues" + }, + "_id": "underscore@1.4.4", + "dist": { + "shasum": "11bea3dc0ae12a258fbcac937e7267ab1e326400" + }, + "_from": "underscore@~1.4.3", + "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore-min.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore-min.js new file mode 100644 index 000000000..c1d9d3aed --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore-min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore.js b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore.js new file mode 100644 index 000000000..a12f0d96c --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/node_modules/underscore/underscore.js @@ -0,0 +1,1226 @@ +// Underscore.js 1.4.4 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.4.4'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? null : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value || _.identity); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(concat.apply(ArrayProto, arguments)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + var args = slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(slice.call(arguments))); + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/package.json b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/package.json new file mode 100644 index 000000000..118036730 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/argparse/package.json @@ -0,0 +1,54 @@ +{ + "name": "argparse", + "description": "Very powerful CLI arguments parser. Native port of argparse - python's options parsing library", + "version": "0.1.15", + "keywords": [ + "cli", + "parser", + "argparse", + "option", + "args" + ], + "homepage": "https://github.com/nodeca/argparse", + "contributors": [ + { + "name": "Eugene Shkuropat" + }, + { + "name": "Paul Jacobson" + } + ], + "bugs": { + "url": "https://github.com/nodeca/argparse/issues" + }, + "license": { + "type": "MIT", + "url": "https://github.com/nodeca/argparse/blob/master/LICENSE" + }, + "repository": { + "type": "git", + "url": "git://github.com/nodeca/argparse.git" + }, + "main": "./index.js", + "scripts": { + "test": "make test" + }, + "dependencies": { + "underscore": "~1.4.3", + "underscore.string": "~2.3.1" + }, + "devDependencies": { + "mocha": "*" + }, + "engines": { + "node": ">= 0.6.0" + }, + "readme": "argparse\n========\n\n[![Build Status](https://secure.travis-ci.org/nodeca/argparse.png?branch=master)](http://travis-ci.org/nodeca/argparse)\n\nCLI arguments parser for node.js. Javascript port of python's\n[argparse](http://docs.python.org/dev/library/argparse.html) module\n(original version 3.2). That's a full port, except some very rare options,\nrecorded in issue tracker.\n\n**NB.** Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/).\n\n\nExample\n=======\n\ntest.js file:\n\n```javascript\n#!/usr/bin/env node\n'use strict';\n\nvar ArgumentParser = require('../lib/argparse').ArgumentParser;\nvar parser = new ArgumentParser({\n version: '0.0.1',\n addHelp:true,\n description: 'Argparse example'\n});\nparser.addArgument(\n [ '-f', '--foo' ],\n {\n help: 'foo bar'\n }\n);\nparser.addArgument(\n [ '-b', '--bar' ],\n {\n help: 'bar foo'\n }\n);\nvar args = parser.parseArgs();\nconsole.dir(args);\n```\n\nDisplay help:\n\n```\n$ ./test.js -h\nusage: example.js [-h] [-v] [-f FOO] [-b BAR]\n\nArgparse example\n\nOptional arguments:\n -h, --help Show this help message and exit.\n -v, --version Show program's version number and exit.\n -f FOO, --foo FOO foo bar\n -b BAR, --bar BAR bar foo\n```\n\nParse arguments:\n\n```\n$ ./test.js -f=3 --bar=4\n{ foo: '3', bar: '4' }\n```\n\nMore [examples](https://github.com/nodeca/argparse/tree/master/examples).\n\n\nArgumentParser objects\n======================\n\n```\nnew ArgumentParser({paramters hash});\n```\n\nCreates a new ArgumentParser object.\n\n**Supported params:**\n\n- ```description``` - Text to display before the argument help.\n- ```epilog``` - Text to display after the argument help.\n- ```addHelp``` - Add a -h/–help option to the parser. (default: True)\n- ```argumentDefault``` - Set the global default value for arguments. (default: None)\n- ```parents``` - A list of ArgumentParser objects whose arguments should also be included.\n- ```prefixChars``` - The set of characters that prefix optional arguments. (default: ‘-‘)\n- ```formatterClass``` - A class for customizing the help output.\n- ```prog``` - The name of the program (default: sys.argv[0])\n- ```usage``` - The string describing the program usage (default: generated)\n- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals.\n\n**Not supportied yet**\n\n- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read.\n\n\nDetails in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects)\n\n\naddArgument() method\n====================\n\n```\nArgumentParser.addArgument([names or flags], {options})\n```\n\nDefines how a single command-line argument should be parsed.\n\n- ```name or flags``` - Either a name or a list of option strings, e.g. foo or -f, --foo.\n\nOptions:\n\n- ```action``` - The basic type of action to be taken when this argument is encountered at the command line.\n- ```nargs```- The number of command-line arguments that should be consumed.\n- ```constant``` - A constant value required by some action and nargs selections.\n- ```defaultValue``` - The value produced if the argument is absent from the command line.\n- ```type``` - The type to which the command-line argument should be converted.\n- ```choices``` - A container of the allowable values for the argument.\n- ```required``` - Whether or not the command-line option may be omitted (optionals only).\n- ```help``` - A brief description of what the argument does.\n- ```metavar``` - A name for the argument in usage messages.\n- ```dest``` - The name of the attribute to be added to the object returned by parseArgs().\n\nDetails in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method)\n\n\nAction (some details)\n================\n\nArgumentParser objects associate command-line arguments with actions.\nThese actions can do just about anything with the command-line arguments associated\nwith them, though most actions simply add an attribute to the object returned by\nparseArgs(). The action keyword argument specifies how the command-line arguments\nshould be handled. The supported actions are:\n\n- ```store``` - Just stores the argument’s value. This is the default action.\n- ```storeConst``` - Stores value, specified by the const keyword argument.\n (Note that the const keyword argument defaults to the rather unhelpful None.)\n The 'storeConst' action is most commonly used with optional arguments, that\n specify some sort of flag.\n- ```storeTrue``` and ```storeFalse``` - Stores values True and False\n respectively. These are special cases of 'storeConst'.\n- ```append``` - Stores a list, and appends each argument value to the list.\n This is useful to allow an option to be specified multiple times.\n- ```appendConst``` - Stores a list, and appends value, specified by the\n const keyword argument to the list. (Note, that the const keyword argument defaults\n is None.) The 'appendConst' action is typically used when multiple arguments need\n to store constants to the same list.\n- ```count``` - Counts the number of times a keyword argument occurs. For example,\n used for increasing verbosity levels.\n- ```help``` - Prints a complete help message for all the options in the current\n parser and then exits. By default a help action is automatically added to the parser.\n See ArgumentParser for details of how the output is created.\n- ```version``` - Prints version information and exit. Expects a `version=`\n keyword argument in the addArgument() call.\n\nDetails in [original action guide](http://docs.python.org/dev/library/argparse.html#action)\n\n\nSub-commands\n============\n\nArgumentParser.addSubparsers()\n\nMany programs split their functionality into a number of sub-commands, for\nexample, the svn program can invoke sub-commands like `svn checkout`, `svn update`,\nand `svn commit`. Splitting up functionality this way can be a particularly good\nidea when a program performs several different functions which require different\nkinds of command-line arguments. `ArgumentParser` supports creation of such\nsub-commands with `addSubparsers()` method. The `addSubparsers()` method is\nnormally called with no arguments and returns an special action object.\nThis object has a single method `addParser()`, which takes a command name and\nany `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object\nthat can be modified as usual.\n\nExample:\n\nsub_commands.js\n```javascript\n#!/usr/bin/env node\n'use strict';\n\nvar ArgumentParser = require('../lib/argparse').ArgumentParser;\nvar parser = new ArgumentParser({\n version: '0.0.1',\n addHelp:true,\n description: 'Argparse examples: sub-commands',\n});\n\nvar subparsers = parser.addSubparsers({\n title:'subcommands',\n dest:\"subcommand_name\"\n});\n\nvar bar = subparsers.addParser('c1', {addHelp:true});\nbar.addArgument(\n [ '-f', '--foo' ],\n {\n action: 'store',\n help: 'foo3 bar3'\n }\n);\nvar bar = subparsers.addParser(\n 'c2',\n {aliases:['co'], addHelp:true}\n);\nbar.addArgument(\n [ '-b', '--bar' ],\n {\n action: 'store',\n type: 'int',\n help: 'foo3 bar3'\n }\n);\n\nvar args = parser.parseArgs();\nconsole.dir(args);\n\n```\n\nDetails in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands)\n\n\nContributors\n============\n\n- [Eugene Shkuropat](https://github.com/shkuropat)\n- [Paul Jacobson](https://github.com/hpaulj)\n\n[others](https://github.com/nodeca/argparse/graphs/contributors)\n\nLicense\n=======\n\nCopyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin).\nReleased under the MIT license. See\n[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details.\n\n\n", + "readmeFilename": "README.md", + "_id": "argparse@0.1.15", + "dist": { + "shasum": "0f513e5ba533598f9e490e9ed7bc508bb3f45edd" + }, + "_from": "argparse@~ 0.1.11", + "_resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.15.tgz" +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/README.md b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/README.md new file mode 100644 index 000000000..a74bd12d6 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/README.md @@ -0,0 +1,73 @@ +**Esprima** ([esprima.org](http://esprima.org)) is a high performance, +standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) +parser written in ECMAScript (also popularly known as +[JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript)). +Esprima is created and maintained by [Ariya Hidayat](http://twitter.com/ariyahidayat), +with the help of [many contributors](https://github.com/ariya/esprima/contributors). + +Esprima runs on web browsers (IE 6+, Firefox 1+, Safari 3+, Chrome 1+, Konqueror 4.6+, Opera 8+) as well as +[Node.js](http://nodejs.org). + +### Features + +- Full support for [ECMAScript 5.1](http://www.ecma-international.org/publications/standards/Ecma-262.htm)(ECMA-262) +- Sensible [syntax tree format](http://esprima.org/doc/index.html#ast) compatible with Mozilla +[Parser AST](https://developer.mozilla.org/en/SpiderMonkey/Parser_API) +- Heavily tested (> 550 [unit tests](http://esprima.org/test/) with solid 100% statement coverage) +- Optional tracking of syntax node location (index-based and line-column) +- Experimental support for ES6/Harmony (module, class, destructuring, ...) + +Esprima is blazing fast (see the [benchmark suite](http://esprima.org/test/benchmarks.html)). +It is up to 3x faster than UglifyJS v1 and it is still [competitive](http://esprima.org/test/compare.html) +with the new generation of fast parsers. + +### Applications + +Esprima serves as the basis for many popular JavaScript development tools: + +- Code coverage analysis: [node-cover](https://github.com/itay/node-cover), [Istanbul](https://github.com/yahoo/Istanbul) +- Documentation tool: [JFDoc](https://github.com/thejohnfreeman/jfdoc), [JSDuck](https://github.com/senchalabs/jsduck) +- Language extension: [LLJS](http://mbebenita.github.com/LLJS/) (low-level JS), +[Sweet.js](http://sweetjs.org/) (macro) +- ES6/Harmony transpiler: [Six](https://github.com/matthewrobb/six), [Harmonizr](https://github.com/jdiamond/harmonizr) +- Eclipse Orion smart editing ([outline view](https://github.com/aclement/esprima-outline), [content assist](http://contraptionsforprogramming.blogspot.com/2012/02/better-javascript-content-assist-in.html)) +- Source code modification: [Esmorph](https://github.com/ariya/esmorph), [Code Painter](https://github.com/fawek/codepainter), +- Source transformation: [node-falafel](https://github.com/substack/node-falafel), [Esmangle](https://github.com/Constellation/esmangle), [escodegen](https://github.com/Constellation/escodegen) + +### Questions? +- [Documentation](http://esprima.org/doc) +- [Issue tracker](http://issues.esprima.org): [known problems](http://code.google.com/p/esprima/issues/list?q=Defect) +and [future plans](http://code.google.com/p/esprima/issues/list?q=Enhancement) +- [Mailing list](http://groups.google.com/group/esprima) +- [Contribution guide](http://esprima.org/doc/index.html#contribution) + +Follow [@Esprima](http://twitter.com/Esprima) on Twitter to get the +development updates. +Feedback and contribution are welcomed! + +### License + +Copyright (C) 2012, 2011 [Ariya Hidayat](http://ariya.ofilabs.com/about) + and other contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * 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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. + diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esparse.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esparse.js new file mode 100755 index 000000000..3e7bb81ea --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esparse.js @@ -0,0 +1,117 @@ +#!/usr/bin/env node +/* + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint sloppy:true node:true rhino:true */ + +var fs, esprima, fname, content, options, syntax; + +if (typeof require === 'function') { + fs = require('fs'); + esprima = require('esprima'); +} else if (typeof load === 'function') { + try { + load('esprima.js'); + } catch (e) { + load('../esprima.js'); + } +} + +// Shims to Node.js objects when running under Rhino. +if (typeof console === 'undefined' && typeof process === 'undefined') { + console = { log: print }; + fs = { readFileSync: readFile }; + process = { argv: arguments, exit: quit }; + process.argv.unshift('esparse.js'); + process.argv.unshift('rhino'); +} + +function showUsage() { + console.log('Usage:'); + console.log(' esparse [options] file.js'); + console.log(); + console.log('Available options:'); + console.log(); + console.log(' --comment Gather all line and block comments in an array'); + console.log(' --loc Include line-column location info for each syntax node'); + console.log(' --range Include index-based range for each syntax node'); + console.log(' --raw Display the raw value of literals'); + console.log(' --tokens List all tokens in an array'); + console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)'); + console.log(' -v, --version Shows program version'); + console.log(); + process.exit(1); +} + +if (process.argv.length <= 2) { + showUsage(); +} + +options = {}; + +process.argv.splice(2).forEach(function (entry) { + + if (entry === '-h' || entry === '--help') { + showUsage(); + } else if (entry === '-v' || entry === '--version') { + console.log('ECMAScript Parser (using Esprima version', esprima.version, ')'); + console.log(); + process.exit(0); + } else if (entry === '--comment') { + options.comment = true; + } else if (entry === '--loc') { + options.loc = true; + } else if (entry === '--range') { + options.range = true; + } else if (entry === '--raw') { + options.raw = true; + } else if (entry === '--tokens') { + options.tokens = true; + } else if (entry === '--tolerant') { + options.tolerant = true; + } else if (entry.slice(0, 2) === '--') { + console.log('Error: unknown option ' + entry + '.'); + process.exit(1); + } else if (typeof fname === 'string') { + console.log('Error: more than one input file.'); + process.exit(1); + } else { + fname = entry; + } +}); + +if (typeof fname !== 'string') { + console.log('Error: no input file.'); + process.exit(1); +} + +try { + content = fs.readFileSync(fname, 'utf-8'); + syntax = esprima.parse(content, options); + console.log(JSON.stringify(syntax, null, 4)); +} catch (e) { + console.log('Error: ' + e.message); + process.exit(1); +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esvalidate.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esvalidate.js new file mode 100755 index 000000000..e0af3f705 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/bin/esvalidate.js @@ -0,0 +1,177 @@ +#!/usr/bin/env node +/* + Copyright (C) 2012 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint sloppy:true plusplus:true node:true rhino:true */ + +var fs, esprima, options, fnames, count; + +if (typeof require === 'function') { + fs = require('fs'); + esprima = require('esprima'); +} else if (typeof load === 'function') { + try { + load('esprima.js'); + } catch (e) { + load('../esprima.js'); + } +} + +// Shims to Node.js objects when running under Rhino. +if (typeof console === 'undefined' && typeof process === 'undefined') { + console = { log: print }; + fs = { readFileSync: readFile }; + process = { argv: arguments, exit: quit }; + process.argv.unshift('esvalidate.js'); + process.argv.unshift('rhino'); +} + +function showUsage() { + console.log('Usage:'); + console.log(' esvalidate [options] file.js'); + console.log(); + console.log('Available options:'); + console.log(); + console.log(' --format=type Set the report format, plain (default) or junit'); + console.log(' -v, --version Print program version'); + console.log(); + process.exit(1); +} + +if (process.argv.length <= 2) { + showUsage(); +} + +options = { + format: 'plain' +}; + +fnames = []; + +process.argv.splice(2).forEach(function (entry) { + + if (entry === '-h' || entry === '--help') { + showUsage(); + } else if (entry === '-v' || entry === '--version') { + console.log('ECMAScript Validator (using Esprima version', esprima.version, ')'); + console.log(); + process.exit(0); + } else if (entry.slice(0, 9) === '--format=') { + options.format = entry.slice(9); + if (options.format !== 'plain' && options.format !== 'junit') { + console.log('Error: unknown report format ' + options.format + '.'); + process.exit(1); + } + } else if (entry.slice(0, 2) === '--') { + console.log('Error: unknown option ' + entry + '.'); + process.exit(1); + } else { + fnames.push(entry); + } +}); + +if (fnames.length === 0) { + console.log('Error: no input file.'); + process.exit(1); +} + +if (options.format === 'junit') { + console.log(''); + console.log(''); +} + +count = 0; +fnames.forEach(function (fname) { + var content, timestamp, syntax, name; + try { + content = fs.readFileSync(fname, 'utf-8'); + + if (content[0] === '#' && content[1] === '!') { + content = '//' + content.substr(2, content.length); + } + + timestamp = Date.now(); + syntax = esprima.parse(content, { tolerant: true }); + + if (options.format === 'junit') { + + name = fname; + if (name.lastIndexOf('/') >= 0) { + name = name.slice(name.lastIndexOf('/') + 1); + } + + console.log(''); + + syntax.errors.forEach(function (error) { + var msg = error.message; + msg = msg.replace(/^Line\ [0-9]*\:\ /, ''); + console.log(' '); + console.log(' ' + + error.message + '(' + name + ':' + error.lineNumber + ')' + + ''); + console.log(' '); + }); + + console.log(''); + + } else if (options.format === 'plain') { + + syntax.errors.forEach(function (error) { + var msg = error.message; + msg = msg.replace(/^Line\ [0-9]*\:\ /, ''); + msg = fname + ':' + error.lineNumber + ': ' + msg; + console.log(msg); + ++count; + }); + + } + } catch (e) { + ++count; + if (options.format === 'junit') { + console.log(''); + console.log(' '); + console.log(' ' + + e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') + + ')'); + console.log(' '); + console.log(''); + } else { + console.log('Error: ' + e.message); + } + } +}); + +if (options.format === 'junit') { + console.log(''); +} + +if (count > 0) { + process.exit(1); +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/esprima.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/esprima.js new file mode 100644 index 000000000..f1320daf9 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/esprima.js @@ -0,0 +1,3908 @@ +/* + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint bitwise:true plusplus:true */ +/*global esprima:true, define:true, exports:true, window: true, +throwError: true, createLiteral: true, generateStatement: true, +parseAssignmentExpression: true, parseBlock: true, parseExpression: true, +parseFunctionDeclaration: true, parseFunctionExpression: true, +parseFunctionSourceElements: true, parseVariableIdentifier: true, +parseLeftHandSideExpression: true, +parseStatement: true, parseSourceElement: true */ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + Syntax, + PropertyKind, + Messages, + Regex, + source, + strict, + index, + lineNumber, + lineStart, + length, + buffer, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + ArrayExpression: 'ArrayExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement' + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalReturn: 'Illegal return statement', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function sliceSource(from, to) { + return source.slice(from, to); + } + + if (typeof 'esprima'[0] === 'undefined') { + sliceSource = function sliceArraySource(from, to) { + return source.slice(from, to).join(''); + }; + } + + function isDecimalDigit(ch) { + return '0123456789'.indexOf(ch) >= 0; + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') || + (ch === '\u000C') || (ch === '\u00A0') || + (ch.charCodeAt(0) >= 0x1680 && + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029'); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === '$') || (ch === '_') || (ch === '\\') || + (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch)); + } + + function isIdentifierPart(ch) { + return (ch === '$') || (ch === '_') || (ch === '\\') || + (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + ((ch >= '0') && (ch <= '9')) || + ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch)); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + + // Future reserved words. + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + } + + return false; + } + + function isStrictModeReservedWord(id) { + switch (id) { + + // Strict Mode reserved words. + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + } + + return false; + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + var keyword = false; + switch (id.length) { + case 2: + keyword = (id === 'if') || (id === 'in') || (id === 'do'); + break; + case 3: + keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); + break; + case 4: + keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with'); + break; + case 5: + keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw'); + break; + case 6: + keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch'); + break; + case 7: + keyword = (id === 'default') || (id === 'finally'); + break; + case 8: + keyword = (id === 'function') || (id === 'continue') || (id === 'debugger'); + break; + case 10: + keyword = (id === 'instanceof'); + break; + } + + if (keyword) { + return true; + } + + switch (id) { + // Future reserved words. + // 'const' is specialized as Keyword in V8. + case 'const': + return true; + + // For compatiblity to SpiderMonkey and ES.next + case 'yield': + case 'let': + return true; + } + + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + return isFutureReservedWord(id); + } + + // 7.4 Comments + + function skipComment() { + var ch, blockComment, lineComment; + + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch)) { + lineComment = false; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + ++index; + blockComment = false; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + index += 2; + lineComment = true; + } else if (ch === '*') { + index += 2; + blockComment = true; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanIdentifier() { + var ch, start, id, restore; + + ch = source[index]; + if (!isIdentifierStart(ch)) { + return; + } + + start = index; + if (ch === '\\') { + ++index; + if (source[index] !== 'u') { + return; + } + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + if (ch === '\\' || !isIdentifierStart(ch)) { + return; + } + id = ch; + } else { + index = restore; + id = 'u'; + } + } else { + id = source[index++]; + } + + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch)) { + break; + } + if (ch === '\\') { + ++index; + if (source[index] !== 'u') { + return; + } + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + if (ch === '\\' || !isIdentifierPart(ch)) { + return; + } + id += ch; + } else { + index = restore; + id += 'u'; + } + } else { + id += source[index++]; + } + } + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + return { + type: Token.Identifier, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (isKeyword(id)) { + return { + type: Token.Keyword, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.1 Null Literals + + if (id === 'null') { + return { + type: Token.NullLiteral, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.2 Boolean Literals + + if (id === 'true' || id === 'false') { + return { + type: Token.BooleanLiteral, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + return { + type: Token.Identifier, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + ch1 = source[index], + ch2, + ch3, + ch4; + + // Check for most common single-character punctuators. + + if (ch1 === ';' || ch1 === '{' || ch1 === '}') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === ',' || ch1 === '(' || ch1 === ')') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Dot (.) can also start a floating-point number, hence the need + // to check the next character. + + ch2 = source[index + 1]; + if (ch1 === '.' && !isDecimalDigit(ch2)) { + return { + type: Token.Punctuator, + value: source[index++], + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Peek more characters. + + ch3 = source[index + 2]; + ch4 = source[index + 3]; + + // 4-character punctuator: >>>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch4 === '=') { + index += 4; + return { + type: Token.Punctuator, + value: '>>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === '=' && ch2 === '=' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '===', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '!' && ch2 === '=' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '!==', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + index += 3; + return { + type: Token.Punctuator, + value: '>>>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '<<=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 2-character punctuators: <= >= == != ++ -- << >> && || + // += -= *= %= &= |= ^= /= + + if (ch2 === '=') { + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + if ('+-<>&|'.indexOf(ch2) >= 0) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // The remaining 1-character punctuators. + + if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) { + return { + type: Token.Punctuator, + value: source[index++], + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 7.8.3 Numeric Literals + + function scanNumericLiteral() { + var number, start, ch; + + ch = source[index]; + assert(isDecimalDigit(ch) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isHexDigit(ch)) { + break; + } + number += source[index++]; + } + + if (number.length <= 2) { + // only 0x + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } else if (isOctalDigit(ch)) { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isOctalDigit(ch)) { + break; + } + number += source[index++]; + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: true, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // decimal number starts with '0' such as '09' is illegal. + if (isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } + + if (ch === '.') { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + + ch = source[index]; + if (isDecimalDigit(ch)) { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } else { + ch = 'character ' + ch; + if (index >= length) { + ch = ''; + } + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch)) { + switch (ch) { + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'u': + case 'x': + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch)) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanRegExp() { + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + + buffer = null; + skipComment(); + + start = index; + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + while (index < length) { + ch = source[index++]; + str += ch; + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch)) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } else if (isLineTerminator(ch)) { + throwError({}, Messages.UnterminatedRegExp); + } + } + } + + if (!terminated) { + throwError({}, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + pattern = str.substr(1, str.length - 2); + + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch)) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + str += '\\u'; + for (; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + } else { + str += '\\'; + } + } else { + flags += ch; + str += ch; + } + } + + try { + value = new RegExp(pattern, flags); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + return { + literal: str, + value: value, + range: [start, index] + }; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advance() { + var ch, token; + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + range: [index, index] + }; + } + + token = scanPunctuator(); + if (typeof token !== 'undefined') { + return token; + } + + ch = source[index]; + + if (ch === '\'' || ch === '"') { + return scanStringLiteral(); + } + + if (ch === '.' || isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + token = scanIdentifier(); + if (typeof token !== 'undefined') { + return token; + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + function lex() { + var token; + + if (buffer) { + index = buffer.range[1]; + lineNumber = buffer.lineNumber; + lineStart = buffer.lineStart; + token = buffer; + buffer = null; + return token; + } + + buffer = null; + return advance(); + } + + function lookahead() { + var pos, line, start; + + if (buffer !== null) { + return buffer; + } + + pos = index; + line = lineNumber; + start = lineStart; + buffer = advance(); + index = pos; + lineNumber = line; + lineStart = start; + + return buffer; + } + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + // Throw an exception + + function throwError(token, messageFormat) { + var error, + args = Array.prototype.slice.call(arguments, 2), + msg = messageFormat.replace( + /%(\d)/g, + function (whole, index) { + return args[index] || ''; + } + ); + + if (typeof token.lineNumber === 'number') { + error = new Error('Line ' + token.lineNumber + ': ' + msg); + error.index = token.range[0]; + error.lineNumber = token.lineNumber; + error.column = token.range[0] - lineStart + 1; + } else { + error = new Error('Line ' + lineNumber + ': ' + msg); + error.index = index; + error.lineNumber = lineNumber; + error.column = index - lineStart + 1; + } + + throw error; + } + + function throwErrorTolerant() { + try { + throwError.apply(null, arguments); + } catch (e) { + if (extra.errors) { + extra.errors.push(e); + } else { + throw e; + } + } + } + + + // Throw an exception because of the token. + + function throwUnexpected(token) { + if (token.type === Token.EOF) { + throwError(token, Messages.UnexpectedEOS); + } + + if (token.type === Token.NumericLiteral) { + throwError(token, Messages.UnexpectedNumber); + } + + if (token.type === Token.StringLiteral) { + throwError(token, Messages.UnexpectedString); + } + + if (token.type === Token.Identifier) { + throwError(token, Messages.UnexpectedIdentifier); + } + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + throwError(token, Messages.UnexpectedReserved); + } else if (strict && isStrictModeReservedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictReservedWord); + return; + } + throwError(token, Messages.UnexpectedToken, token.value); + } + + // BooleanLiteral, NullLiteral, or Punctuator. + throwError(token, Messages.UnexpectedToken, token.value); + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpected(token); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpected(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + var token = lookahead(); + return token.type === Token.Punctuator && token.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + var token = lookahead(); + return token.type === Token.Keyword && token.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var token = lookahead(), + op = token.value; + + if (token.type !== Token.Punctuator) { + return false; + } + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var token, line; + + // Catch the very common case first. + if (source[index] === ';') { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + return; + } + + if (match(';')) { + lex(); + return; + } + + token = lookahead(); + if (token.type !== Token.EOF && !match('}')) { + throwUnexpected(token); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = []; + + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + elements.push(parseAssignmentExpression()); + + if (!match(']')) { + expect(','); + } + } + } + + expect(']'); + + return { + type: Syntax.ArrayExpression, + elements: elements + }; + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(param, first) { + var previousStrict, body; + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (first && strict && isRestrictedWord(param[0].name)) { + throwErrorTolerant(first, Messages.StrictParamName); + } + strict = previousStrict; + + return { + type: Syntax.FunctionExpression, + id: null, + params: param, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + function parseObjectPropertyKey() { + var token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return createLiteral(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseObjectProperty() { + var token, key, id, param; + + token = lookahead(); + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !match(':')) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction([]), + kind: 'get' + }; + } else if (token.value === 'set' && !match(':')) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead(); + if (token.type !== Token.Identifier) { + expect(')'); + throwErrorTolerant(token, Messages.UnexpectedToken, token.value); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction([]), + kind: 'set' + }; + } else { + param = [ parseVariableIdentifier() ]; + expect(')'); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction(param, token), + kind: 'set' + }; + } + } else { + expect(':'); + return { + type: Syntax.Property, + key: id, + value: parseAssignmentExpression(), + kind: 'init' + }; + } + } else if (token.type === Token.EOF || token.type === Token.Punctuator) { + throwUnexpected(token); + } else { + key = parseObjectPropertyKey(); + expect(':'); + return { + type: Syntax.Property, + key: key, + value: parseAssignmentExpression(), + kind: 'init' + }; + } + } + + function parseObjectInitialiser() { + var properties = [], property, name, kind, map = {}, toString = String; + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + if (Object.prototype.hasOwnProperty.call(map, name)) { + if (map[name] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[name] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[name] |= kind; + } else { + map[name] = kind; + } + + properties.push(property); + + if (!match('}')) { + expect(','); + } + } + + expect('}'); + + return { + type: Syntax.ObjectExpression, + properties: properties + }; + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + expr = parseExpression(); + + expect(')'); + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var token = lookahead(), + type = token.type; + + if (type === Token.Identifier) { + return { + type: Syntax.Identifier, + name: lex().value + }; + } + + if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return createLiteral(lex()); + } + + if (type === Token.Keyword) { + if (matchKeyword('this')) { + lex(); + return { + type: Syntax.ThisExpression + }; + } + + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + } + + if (type === Token.BooleanLiteral) { + lex(); + token.value = (token.value === 'true'); + return createLiteral(token); + } + + if (type === Token.NullLiteral) { + lex(); + token.value = null; + return createLiteral(token); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('/') || match('/=')) { + return createLiteral(scanRegExp()); + } + + return throwUnexpected(lex()); + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = []; + + expect('('); + + if (!match(')')) { + while (index < length) { + args.push(parseAssignmentExpression()); + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + return args; + } + + function parseNonComputedProperty() { + var token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpected(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var expr; + + expectKeyword('new'); + + expr = { + type: Syntax.NewExpression, + callee: parseLeftHandSideExpression(), + 'arguments': [] + }; + + if (match('(')) { + expr['arguments'] = parseArguments(); + } + + return expr; + } + + function parseLeftHandSideExpressionAllowCall() { + var expr; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(')) { + if (match('(')) { + expr = { + type: Syntax.CallExpression, + callee: expr, + 'arguments': parseArguments() + }; + } else if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + } + } + + return expr; + } + + + function parseLeftHandSideExpression() { + var expr; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[')) { + if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + } + } + + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr = parseLeftHandSideExpressionAllowCall(), token; + + token = lookahead(); + if (token.type !== Token.Punctuator) { + return expr; + } + + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPostfix); + } + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + expr = { + type: Syntax.UpdateExpression, + operator: lex().value, + argument: expr, + prefix: false + }; + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr; + + token = lookahead(); + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return parsePostfixExpression(); + } + + if (match('++') || match('--')) { + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + expr = { + type: Syntax.UpdateExpression, + operator: token.value, + argument: expr, + prefix: true + }; + return expr; + } + + if (match('+') || match('-') || match('~') || match('!')) { + expr = { + type: Syntax.UnaryExpression, + operator: lex().value, + argument: parseUnaryExpression(), + prefix: true + }; + return expr; + } + + if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + expr = { + type: Syntax.UnaryExpression, + operator: lex().value, + argument: parseUnaryExpression(), + prefix: true + }; + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + throwErrorTolerant({}, Messages.StrictDelete); + } + return expr; + } + + return parsePostfixExpression(); + } + + // 11.5 Multiplicative Operators + + function parseMultiplicativeExpression() { + var expr = parseUnaryExpression(); + + while (match('*') || match('/') || match('%')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseUnaryExpression() + }; + } + + return expr; + } + + // 11.6 Additive Operators + + function parseAdditiveExpression() { + var expr = parseMultiplicativeExpression(); + + while (match('+') || match('-')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseMultiplicativeExpression() + }; + } + + return expr; + } + + // 11.7 Bitwise Shift Operators + + function parseShiftExpression() { + var expr = parseAdditiveExpression(); + + while (match('<<') || match('>>') || match('>>>')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseAdditiveExpression() + }; + } + + return expr; + } + // 11.8 Relational Operators + + function parseRelationalExpression() { + var expr, previousAllowIn; + + previousAllowIn = state.allowIn; + state.allowIn = true; + + expr = parseShiftExpression(); + + while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseShiftExpression() + }; + } + + state.allowIn = previousAllowIn; + return expr; + } + + // 11.9 Equality Operators + + function parseEqualityExpression() { + var expr = parseRelationalExpression(); + + while (match('==') || match('!=') || match('===') || match('!==')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseRelationalExpression() + }; + } + + return expr; + } + + // 11.10 Binary Bitwise Operators + + function parseBitwiseANDExpression() { + var expr = parseEqualityExpression(); + + while (match('&')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '&', + left: expr, + right: parseEqualityExpression() + }; + } + + return expr; + } + + function parseBitwiseXORExpression() { + var expr = parseBitwiseANDExpression(); + + while (match('^')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '^', + left: expr, + right: parseBitwiseANDExpression() + }; + } + + return expr; + } + + function parseBitwiseORExpression() { + var expr = parseBitwiseXORExpression(); + + while (match('|')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '|', + left: expr, + right: parseBitwiseXORExpression() + }; + } + + return expr; + } + + // 11.11 Binary Logical Operators + + function parseLogicalANDExpression() { + var expr = parseBitwiseORExpression(); + + while (match('&&')) { + lex(); + expr = { + type: Syntax.LogicalExpression, + operator: '&&', + left: expr, + right: parseBitwiseORExpression() + }; + } + + return expr; + } + + function parseLogicalORExpression() { + var expr = parseLogicalANDExpression(); + + while (match('||')) { + lex(); + expr = { + type: Syntax.LogicalExpression, + operator: '||', + left: expr, + right: parseLogicalANDExpression() + }; + } + + return expr; + } + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent; + + expr = parseLogicalORExpression(); + + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + + expr = { + type: Syntax.ConditionalExpression, + test: expr, + consequent: consequent, + alternate: parseAssignmentExpression() + }; + } + + return expr; + } + + // 11.13 Assignment Operators + + function parseAssignmentExpression() { + var token, expr; + + token = lookahead(); + expr = parseConditionalExpression(); + + if (matchAssign()) { + // LeftHandSideExpression + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant(token, Messages.StrictLHSAssignment); + } + + expr = { + type: Syntax.AssignmentExpression, + operator: lex().value, + left: expr, + right: parseAssignmentExpression() + }; + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr = parseAssignmentExpression(); + + if (match(',')) { + expr = { + type: Syntax.SequenceExpression, + expressions: [ expr ] + }; + + while (index < length) { + if (!match(',')) { + break; + } + lex(); + expr.expressions.push(parseAssignmentExpression()); + } + + } + return expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block; + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return { + type: Syntax.BlockStatement, + body: block + }; + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token = lex(); + + if (token.type !== Token.Identifier) { + throwUnexpected(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseVariableDeclaration(kind) { + var id = parseVariableIdentifier(), + init = null; + + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + throwErrorTolerant({}, Messages.StrictVarName); + } + + if (kind === 'const') { + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return { + type: Syntax.VariableDeclarator, + id: id, + init: init + }; + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement() { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: 'var' + }; + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations; + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + expect(';'); + + return { + type: Syntax.EmptyStatement + }; + } + + // 12.4 Expression Statement + + function parseExpressionStatement() { + var expr = parseExpression(); + + consumeSemicolon(); + + return { + type: Syntax.ExpressionStatement, + expression: expr + }; + } + + // 12.5 If statement + + function parseIfStatement() { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return { + type: Syntax.IfStatement, + test: test, + consequent: consequent, + alternate: alternate + }; + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement() { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return { + type: Syntax.DoWhileStatement, + body: body, + test: test + }; + } + + function parseWhileStatement() { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return { + type: Syntax.WhileStatement, + test: test, + body: body + }; + } + + function parseForVariableDeclaration() { + var token = lex(); + + return { + type: Syntax.VariableDeclaration, + declarations: parseVariableDeclarationList(), + kind: token.value + }; + } + + function parseForStatement() { + var init, test, update, left, right, body, oldInIteration; + + init = test = update = null; + + expectKeyword('for'); + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = true; + + if (init.declarations.length === 1 && matchKeyword('in')) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = true; + + if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isLeftHandSide(init)) { + throwErrorTolerant({}, Messages.InvalidLHSInForIn); + } + + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + if (typeof left === 'undefined') { + return { + type: Syntax.ForStatement, + init: init, + test: test, + update: update, + body: body + }; + } + + return { + type: Syntax.ForInStatement, + left: left, + right: right, + body: body, + each: false + }; + } + + // 12.7 The continue statement + + function parseContinueStatement() { + var token, label = null; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source[index] === ';') { + lex(); + + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: null + }; + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: null + }; + } + + token = lookahead(); + if (token.type === Token.Identifier) { + label = parseVariableIdentifier(); + + if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: label + }; + } + + // 12.8 The break statement + + function parseBreakStatement() { + var token, label = null; + + expectKeyword('break'); + + // Optimize the most common form: 'break;'. + if (source[index] === ';') { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: null + }; + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: null + }; + } + + token = lookahead(); + if (token.type === Token.Identifier) { + label = parseVariableIdentifier(); + + if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: label + }; + } + + // 12.9 The return statement + + function parseReturnStatement() { + var token, argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + throwErrorTolerant({}, Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source[index] === ' ') { + if (isIdentifierStart(source[index + 1])) { + argument = parseExpression(); + consumeSemicolon(); + return { + type: Syntax.ReturnStatement, + argument: argument + }; + } + } + + if (peekLineTerminator()) { + return { + type: Syntax.ReturnStatement, + argument: null + }; + } + + if (!match(';')) { + token = lookahead(); + if (!match('}') && token.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return { + type: Syntax.ReturnStatement, + argument: argument + }; + } + + // 12.10 The with statement + + function parseWithStatement() { + var object, body; + + if (strict) { + throwErrorTolerant({}, Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return { + type: Syntax.WithStatement, + object: object, + body: body + }; + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, + consequent = [], + statement; + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + statement = parseStatement(); + if (typeof statement === 'undefined') { + break; + } + consequent.push(statement); + } + + return { + type: Syntax.SwitchCase, + test: test, + consequent: consequent + }; + } + + function parseSwitchStatement() { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError({}, Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + } + + // 12.13 The throw statement + + function parseThrowStatement() { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return { + type: Syntax.ThrowStatement, + argument: argument + }; + } + + // 12.14 The try statement + + function parseCatchClause() { + var param; + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpected(lookahead()); + } + + param = parseVariableIdentifier(); + // 12.14.1 + if (strict && isRestrictedWord(param.name)) { + throwErrorTolerant({}, Messages.StrictCatchVariable); + } + + expect(')'); + + return { + type: Syntax.CatchClause, + param: param, + body: parseBlock() + }; + } + + function parseTryStatement() { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError({}, Messages.NoCatchOrFinally); + } + + return { + type: Syntax.TryStatement, + block: block, + guardedHandlers: [], + handlers: handlers, + finalizer: finalizer + }; + } + + // 12.15 The debugger statement + + function parseDebuggerStatement() { + expectKeyword('debugger'); + + consumeSemicolon(); + + return { + type: Syntax.DebuggerStatement + }; + } + + // 12 Statements + + function parseStatement() { + var token = lookahead(), + expr, + labeledBody; + + if (token.type === Token.EOF) { + throwUnexpected(token); + } + + if (token.type === Token.Punctuator) { + switch (token.value) { + case ';': + return parseEmptyStatement(); + case '{': + return parseBlock(); + case '(': + return parseExpressionStatement(); + default: + break; + } + } + + if (token.type === Token.Keyword) { + switch (token.value) { + case 'break': + return parseBreakStatement(); + case 'continue': + return parseContinueStatement(); + case 'debugger': + return parseDebuggerStatement(); + case 'do': + return parseDoWhileStatement(); + case 'for': + return parseForStatement(); + case 'function': + return parseFunctionDeclaration(); + case 'if': + return parseIfStatement(); + case 'return': + return parseReturnStatement(); + case 'switch': + return parseSwitchStatement(); + case 'throw': + return parseThrowStatement(); + case 'try': + return parseTryStatement(); + case 'var': + return parseVariableStatement(); + case 'while': + return parseWhileStatement(); + case 'with': + return parseWithStatement(); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) { + throwError({}, Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[expr.name] = true; + labeledBody = parseStatement(); + delete state.labelSet[expr.name]; + + return { + type: Syntax.LabeledStatement, + label: expr, + body: labeledBody + }; + } + + consumeSemicolon(); + + return { + type: Syntax.ExpressionStatement, + expression: expr + }; + } + + // 13 Function Definition + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody; + + expect('{'); + + while (index < length) { + token = lookahead(); + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = sliceSource(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + + return { + type: Syntax.BlockStatement, + body: sourceElements + }; + } + + function parseFunctionDeclaration() { + var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet; + + expectKeyword('function'); + token = lookahead(); + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + expect('('); + + if (!match(')')) { + paramSet = {}; + while (index < length) { + token = lookahead(); + param = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + stricted = token; + message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + stricted = token; + message = Messages.StrictParamDupe; + } + } else if (!firstRestricted) { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + firstRestricted = token; + message = Messages.StrictParamDupe; + } + } + params.push(param); + paramSet[param.name] = true; + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && stricted) { + throwErrorTolerant(stricted, message); + } + strict = previousStrict; + + return { + type: Syntax.FunctionDeclaration, + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + function parseFunctionExpression() { + var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet; + + expectKeyword('function'); + + if (!match('(')) { + token = lookahead(); + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + expect('('); + + if (!match(')')) { + paramSet = {}; + while (index < length) { + token = lookahead(); + param = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + stricted = token; + message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + stricted = token; + message = Messages.StrictParamDupe; + } + } else if (!firstRestricted) { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + firstRestricted = token; + message = Messages.StrictParamDupe; + } + } + params.push(param); + paramSet[param.name] = true; + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && stricted) { + throwErrorTolerant(stricted, message); + } + strict = previousStrict; + + return { + type: Syntax.FunctionExpression, + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + // 14 Program + + function parseSourceElement() { + var token = lookahead(); + + if (token.type === Token.Keyword) { + switch (token.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(token.value); + case 'function': + return parseFunctionDeclaration(); + default: + return parseStatement(); + } + } + + if (token.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead(); + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = sliceSource(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseProgram() { + var program; + strict = false; + program = { + type: Syntax.Program, + body: parseSourceElements() + }; + return program; + } + + // The following functions are needed only when the option to preserve + // the comments is active. + + function addComment(type, value, start, end, loc) { + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (extra.comments.length > 0) { + if (extra.comments[extra.comments.length - 1].range[1] > start) { + return; + } + } + + extra.comments.push({ + type: type, + value: value, + range: [start, end], + loc: loc + }); + } + + function scanComment() { + var comment, ch, loc, start, blockComment, lineComment; + + comment = ''; + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch)) { + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + lineComment = false; + addComment('Line', comment, start, index - 1, loc); + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + comment = ''; + } else if (index >= length) { + lineComment = false; + comment += ch; + loc.end = { + line: lineNumber, + column: length - lineStart + }; + addComment('Line', comment, start, length, loc); + } else { + comment += ch; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + comment += '\r\n'; + } else { + comment += ch; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + comment += ch; + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + comment = comment.substr(0, comment.length - 1); + blockComment = false; + ++index; + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + comment = ''; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + start = index; + index += 2; + lineComment = true; + if (index >= length) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + lineComment = false; + addComment('Line', comment, start, index, loc); + } + } else if (ch === '*') { + start = index; + index += 2; + blockComment = true; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function filterCommentLocation() { + var i, entry, comment, comments = []; + + for (i = 0; i < extra.comments.length; ++i) { + entry = extra.comments[i]; + comment = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + comment.range = entry.range; + } + if (extra.loc) { + comment.loc = entry.loc; + } + comments.push(comment); + } + + extra.comments = comments; + } + + function collectToken() { + var start, loc, token, range, value; + + skipComment(); + start = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = extra.advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + range = [token.range[0], token.range[1]]; + value = sliceSource(token.range[0], token.range[1]); + extra.tokens.push({ + type: TokenName[token.type], + value: value, + range: range, + loc: loc + }); + } + + return token; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = extra.scanRegExp(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + range: [pos, index], + loc: loc + }); + + return regex; + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function createLiteral(token) { + return { + type: Syntax.Literal, + value: token.value + }; + } + + function createRawLiteral(token) { + return { + type: Syntax.Literal, + value: token.value, + raw: sliceSource(token.range[0], token.range[1]) + }; + } + + function createLocationMarker() { + var marker = {}; + + marker.range = [index, index]; + marker.loc = { + start: { + line: lineNumber, + column: index - lineStart + }, + end: { + line: lineNumber, + column: index - lineStart + } + }; + + marker.end = function () { + this.range[1] = index; + this.loc.end.line = lineNumber; + this.loc.end.column = index - lineStart; + }; + + marker.applyGroup = function (node) { + if (extra.range) { + node.groupRange = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.groupLoc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + } + }; + + marker.apply = function (node) { + if (extra.range) { + node.range = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.loc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + } + }; + + return marker; + } + + function trackGroupExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + expect('('); + + expr = parseExpression(); + + expect(')'); + + marker.end(); + marker.applyGroup(expr); + + return expr; + } + + function trackLeftHandSideExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[')) { + if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + marker.end(); + marker.apply(expr); + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function trackLeftHandSideExpressionAllowCall() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(')) { + if (match('(')) { + expr = { + type: Syntax.CallExpression, + callee: expr, + 'arguments': parseArguments() + }; + marker.end(); + marker.apply(expr); + } else if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + marker.end(); + marker.apply(expr); + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function filterGroup(node) { + var n, i, entry; + + n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; + for (i in node) { + if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { + entry = node[i]; + if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { + n[i] = entry; + } else { + n[i] = filterGroup(entry); + } + } + } + return n; + } + + function wrapTrackingFunction(range, loc) { + + return function (parseFunction) { + + function isBinary(node) { + return node.type === Syntax.LogicalExpression || + node.type === Syntax.BinaryExpression; + } + + function visit(node) { + var start, end; + + if (isBinary(node.left)) { + visit(node.left); + } + if (isBinary(node.right)) { + visit(node.right); + } + + if (range) { + if (node.left.groupRange || node.right.groupRange) { + start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; + end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; + node.range = [start, end]; + } else if (typeof node.range === 'undefined') { + start = node.left.range[0]; + end = node.right.range[1]; + node.range = [start, end]; + } + } + if (loc) { + if (node.left.groupLoc || node.right.groupLoc) { + start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; + end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; + node.loc = { + start: start, + end: end + }; + } else if (typeof node.loc === 'undefined') { + node.loc = { + start: node.left.loc.start, + end: node.right.loc.end + }; + } + } + } + + return function () { + var marker, node; + + skipComment(); + + marker = createLocationMarker(); + node = parseFunction.apply(null, arguments); + marker.end(); + + if (range && typeof node.range === 'undefined') { + marker.apply(node); + } + + if (loc && typeof node.loc === 'undefined') { + marker.apply(node); + } + + if (isBinary(node)) { + visit(node); + } + + return node; + }; + }; + } + + function patch() { + + var wrapTracking; + + if (extra.comments) { + extra.skipComment = skipComment; + skipComment = scanComment; + } + + if (extra.raw) { + extra.createLiteral = createLiteral; + createLiteral = createRawLiteral; + } + + if (extra.range || extra.loc) { + + extra.parseGroupExpression = parseGroupExpression; + extra.parseLeftHandSideExpression = parseLeftHandSideExpression; + extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; + parseGroupExpression = trackGroupExpression; + parseLeftHandSideExpression = trackLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; + + wrapTracking = wrapTrackingFunction(extra.range, extra.loc); + + extra.parseAdditiveExpression = parseAdditiveExpression; + extra.parseAssignmentExpression = parseAssignmentExpression; + extra.parseBitwiseANDExpression = parseBitwiseANDExpression; + extra.parseBitwiseORExpression = parseBitwiseORExpression; + extra.parseBitwiseXORExpression = parseBitwiseXORExpression; + extra.parseBlock = parseBlock; + extra.parseFunctionSourceElements = parseFunctionSourceElements; + extra.parseCatchClause = parseCatchClause; + extra.parseComputedMember = parseComputedMember; + extra.parseConditionalExpression = parseConditionalExpression; + extra.parseConstLetDeclaration = parseConstLetDeclaration; + extra.parseEqualityExpression = parseEqualityExpression; + extra.parseExpression = parseExpression; + extra.parseForVariableDeclaration = parseForVariableDeclaration; + extra.parseFunctionDeclaration = parseFunctionDeclaration; + extra.parseFunctionExpression = parseFunctionExpression; + extra.parseLogicalANDExpression = parseLogicalANDExpression; + extra.parseLogicalORExpression = parseLogicalORExpression; + extra.parseMultiplicativeExpression = parseMultiplicativeExpression; + extra.parseNewExpression = parseNewExpression; + extra.parseNonComputedProperty = parseNonComputedProperty; + extra.parseObjectProperty = parseObjectProperty; + extra.parseObjectPropertyKey = parseObjectPropertyKey; + extra.parsePostfixExpression = parsePostfixExpression; + extra.parsePrimaryExpression = parsePrimaryExpression; + extra.parseProgram = parseProgram; + extra.parsePropertyFunction = parsePropertyFunction; + extra.parseRelationalExpression = parseRelationalExpression; + extra.parseStatement = parseStatement; + extra.parseShiftExpression = parseShiftExpression; + extra.parseSwitchCase = parseSwitchCase; + extra.parseUnaryExpression = parseUnaryExpression; + extra.parseVariableDeclaration = parseVariableDeclaration; + extra.parseVariableIdentifier = parseVariableIdentifier; + + parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression); + parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); + parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression); + parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression); + parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression); + parseBlock = wrapTracking(extra.parseBlock); + parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); + parseCatchClause = wrapTracking(extra.parseCatchClause); + parseComputedMember = wrapTracking(extra.parseComputedMember); + parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); + parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); + parseEqualityExpression = wrapTracking(extra.parseEqualityExpression); + parseExpression = wrapTracking(extra.parseExpression); + parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); + parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); + parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); + parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); + parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression); + parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression); + parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression); + parseNewExpression = wrapTracking(extra.parseNewExpression); + parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); + parseObjectProperty = wrapTracking(extra.parseObjectProperty); + parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); + parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); + parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); + parseProgram = wrapTracking(extra.parseProgram); + parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); + parseRelationalExpression = wrapTracking(extra.parseRelationalExpression); + parseStatement = wrapTracking(extra.parseStatement); + parseShiftExpression = wrapTracking(extra.parseShiftExpression); + parseSwitchCase = wrapTracking(extra.parseSwitchCase); + parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); + parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); + parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); + } + + if (typeof extra.tokens !== 'undefined') { + extra.advance = advance; + extra.scanRegExp = scanRegExp; + + advance = collectToken; + scanRegExp = collectRegex; + } + } + + function unpatch() { + if (typeof extra.skipComment === 'function') { + skipComment = extra.skipComment; + } + + if (extra.raw) { + createLiteral = extra.createLiteral; + } + + if (extra.range || extra.loc) { + parseAdditiveExpression = extra.parseAdditiveExpression; + parseAssignmentExpression = extra.parseAssignmentExpression; + parseBitwiseANDExpression = extra.parseBitwiseANDExpression; + parseBitwiseORExpression = extra.parseBitwiseORExpression; + parseBitwiseXORExpression = extra.parseBitwiseXORExpression; + parseBlock = extra.parseBlock; + parseFunctionSourceElements = extra.parseFunctionSourceElements; + parseCatchClause = extra.parseCatchClause; + parseComputedMember = extra.parseComputedMember; + parseConditionalExpression = extra.parseConditionalExpression; + parseConstLetDeclaration = extra.parseConstLetDeclaration; + parseEqualityExpression = extra.parseEqualityExpression; + parseExpression = extra.parseExpression; + parseForVariableDeclaration = extra.parseForVariableDeclaration; + parseFunctionDeclaration = extra.parseFunctionDeclaration; + parseFunctionExpression = extra.parseFunctionExpression; + parseGroupExpression = extra.parseGroupExpression; + parseLeftHandSideExpression = extra.parseLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; + parseLogicalANDExpression = extra.parseLogicalANDExpression; + parseLogicalORExpression = extra.parseLogicalORExpression; + parseMultiplicativeExpression = extra.parseMultiplicativeExpression; + parseNewExpression = extra.parseNewExpression; + parseNonComputedProperty = extra.parseNonComputedProperty; + parseObjectProperty = extra.parseObjectProperty; + parseObjectPropertyKey = extra.parseObjectPropertyKey; + parsePrimaryExpression = extra.parsePrimaryExpression; + parsePostfixExpression = extra.parsePostfixExpression; + parseProgram = extra.parseProgram; + parsePropertyFunction = extra.parsePropertyFunction; + parseRelationalExpression = extra.parseRelationalExpression; + parseStatement = extra.parseStatement; + parseShiftExpression = extra.parseShiftExpression; + parseSwitchCase = extra.parseSwitchCase; + parseUnaryExpression = extra.parseUnaryExpression; + parseVariableDeclaration = extra.parseVariableDeclaration; + parseVariableIdentifier = extra.parseVariableIdentifier; + } + + if (typeof extra.scanRegExp === 'function') { + advance = extra.advance; + scanRegExp = extra.scanRegExp; + } + } + + function stringToArray(str) { + var length = str.length, + result = [], + i; + for (i = 0; i < length; ++i) { + result[i] = str.charAt(i); + } + return result; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + buffer = null; + state = { + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.raw = (typeof options.raw === 'boolean') && options.raw; + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + + // Force accessing the characters via an array. + if (typeof source[0] === 'undefined') { + source = stringToArray(code); + } + } + } + + patch(); + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + if (extra.range || extra.loc) { + program.body = filterGroup(program.body); + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + + return program; + } + + // Sync with package.json. + exports.version = '1.0.4'; + + exports.parse = parse; + + // Deep copy. + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/package.json b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/package.json new file mode 100644 index 000000000..c8b882043 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/package.json @@ -0,0 +1,63 @@ +{ + "name": "esprima", + "description": "ECMAScript parsing infrastructure for multipurpose analysis", + "homepage": "http://esprima.org", + "main": "esprima.js", + "bin": { + "esparse": "./bin/esparse.js", + "esvalidate": "./bin/esvalidate.js" + }, + "files": [ + "bin", + "test/run.js", + "test/runner.js", + "test/test.js", + "test/compat.js", + "test/reflect.js", + "esprima.js" + ], + "version": "1.0.4", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Ariya Hidayat", + "email": "ariya.hidayat@gmail.com", + "url": "http://ariya.ofilabs.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/ariya/esprima.git" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://github.com/ariya/esprima/raw/master/LICENSE.BSD" + } + ], + "keywords": [ + "ast", + "ecmascript", + "javascript", + "parser", + "syntax" + ], + "scripts": { + "test": "node test/run.js", + "benchmark": "node test/benchmarks.js", + "benchmark-quick": "node test/benchmarks.js quick" + }, + "readme": "**Esprima** ([esprima.org](http://esprima.org)) is a high performance,\nstandard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)\nparser written in ECMAScript (also popularly known as\n[JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript)).\nEsprima is created and maintained by [Ariya Hidayat](http://twitter.com/ariyahidayat),\nwith the help of [many contributors](https://github.com/ariya/esprima/contributors).\n\nEsprima runs on web browsers (IE 6+, Firefox 1+, Safari 3+, Chrome 1+, Konqueror 4.6+, Opera 8+) as well as\n[Node.js](http://nodejs.org).\n\n### Features\n\n- Full support for [ECMAScript 5.1](http://www.ecma-international.org/publications/standards/Ecma-262.htm)(ECMA-262)\n- Sensible [syntax tree format](http://esprima.org/doc/index.html#ast) compatible with Mozilla\n[Parser AST](https://developer.mozilla.org/en/SpiderMonkey/Parser_API)\n- Heavily tested (> 550 [unit tests](http://esprima.org/test/) with solid 100% statement coverage)\n- Optional tracking of syntax node location (index-based and line-column)\n- Experimental support for ES6/Harmony (module, class, destructuring, ...)\n\nEsprima is blazing fast (see the [benchmark suite](http://esprima.org/test/benchmarks.html)).\nIt is up to 3x faster than UglifyJS v1 and it is still [competitive](http://esprima.org/test/compare.html)\nwith the new generation of fast parsers.\n\n### Applications\n\nEsprima serves as the basis for many popular JavaScript development tools:\n\n- Code coverage analysis: [node-cover](https://github.com/itay/node-cover), [Istanbul](https://github.com/yahoo/Istanbul)\n- Documentation tool: [JFDoc](https://github.com/thejohnfreeman/jfdoc), [JSDuck](https://github.com/senchalabs/jsduck)\n- Language extension: [LLJS](http://mbebenita.github.com/LLJS/) (low-level JS),\n[Sweet.js](http://sweetjs.org/) (macro)\n- ES6/Harmony transpiler: [Six](https://github.com/matthewrobb/six), [Harmonizr](https://github.com/jdiamond/harmonizr)\n- Eclipse Orion smart editing ([outline view](https://github.com/aclement/esprima-outline), [content assist](http://contraptionsforprogramming.blogspot.com/2012/02/better-javascript-content-assist-in.html))\n- Source code modification: [Esmorph](https://github.com/ariya/esmorph), [Code Painter](https://github.com/fawek/codepainter),\n- Source transformation: [node-falafel](https://github.com/substack/node-falafel), [Esmangle](https://github.com/Constellation/esmangle), [escodegen](https://github.com/Constellation/escodegen)\n\n### Questions?\n- [Documentation](http://esprima.org/doc)\n- [Issue tracker](http://issues.esprima.org): [known problems](http://code.google.com/p/esprima/issues/list?q=Defect)\nand [future plans](http://code.google.com/p/esprima/issues/list?q=Enhancement)\n- [Mailing list](http://groups.google.com/group/esprima)\n- [Contribution guide](http://esprima.org/doc/index.html#contribution)\n\nFollow [@Esprima](http://twitter.com/Esprima) on Twitter to get the\ndevelopment updates.\nFeedback and contribution are welcomed!\n\n### License\n\nCopyright (C) 2012, 2011 [Ariya Hidayat](http://ariya.ofilabs.com/about)\n and other contributors.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/ariya/esprima/issues" + }, + "_id": "esprima@1.0.4", + "dist": { + "shasum": "0ba4feed47fb98891b3353322b533f6f2fd37235" + }, + "_from": "esprima@~ 1.0.2", + "_resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/compat.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/compat.js new file mode 100644 index 000000000..ee3a6295e --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/compat.js @@ -0,0 +1,239 @@ +/* + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint node: true */ +/*global document: true, window:true, esprima: true, testReflect: true */ + +var runTests; + +function getContext(esprima, reportCase, reportFailure) { + 'use strict'; + + var Reflect, Pattern; + + // Maps Mozilla Reflect object to our Esprima parser. + Reflect = { + parse: function (code) { + var result; + + reportCase(code); + + try { + result = esprima.parse(code); + } catch (error) { + result = error; + } + + return result; + } + }; + + // This is used by Reflect test suite to match a syntax tree. + Pattern = function (obj) { + var pattern; + + // Poor man's deep object cloning. + pattern = JSON.parse(JSON.stringify(obj)); + + // Special handling for regular expression literal since we need to + // convert it to a string literal, otherwise it will be decoded + // as object "{}" and the regular expression would be lost. + if (obj.type && obj.type === 'Literal') { + if (obj.value instanceof RegExp) { + pattern = { + type: obj.type, + value: obj.value.toString() + }; + } + } + + // Special handling for branch statement because SpiderMonkey + // prefers to put the 'alternate' property before 'consequent'. + if (obj.type && obj.type === 'IfStatement') { + pattern = { + type: pattern.type, + test: pattern.test, + consequent: pattern.consequent, + alternate: pattern.alternate + }; + } + + // Special handling for do while statement because SpiderMonkey + // prefers to put the 'test' property before 'body'. + if (obj.type && obj.type === 'DoWhileStatement') { + pattern = { + type: pattern.type, + body: pattern.body, + test: pattern.test + }; + } + + function adjustRegexLiteralAndRaw(key, value) { + if (key === 'value' && value instanceof RegExp) { + value = value.toString(); + } else if (key === 'raw' && typeof value === "string") { + // Ignore Esprima-specific 'raw' property. + return undefined; + } + return value; + } + + if (obj.type && (obj.type === 'Program')) { + pattern.assert = function (tree) { + var actual, expected; + actual = JSON.stringify(tree, adjustRegexLiteralAndRaw, 4); + expected = JSON.stringify(obj, null, 4); + + if (expected !== actual) { + reportFailure(expected, actual); + } + }; + } + + return pattern; + }; + + return { + Reflect: Reflect, + Pattern: Pattern + }; +} + +if (typeof window !== 'undefined') { + // Run all tests in a browser environment. + runTests = function () { + 'use strict'; + + var total = 0, + failures = 0; + + function setText(el, str) { + if (typeof el.innerText === 'string') { + el.innerText = str; + } else { + el.textContent = str; + } + } + + function reportCase(code) { + var report, e; + report = document.getElementById('report'); + e = document.createElement('pre'); + e.setAttribute('class', 'code'); + setText(e, code); + report.appendChild(e); + total += 1; + } + + function reportFailure(expected, actual) { + var report, e; + + failures += 1; + + report = document.getElementById('report'); + + e = document.createElement('p'); + setText(e, 'Expected'); + report.appendChild(e); + + e = document.createElement('pre'); + e.setAttribute('class', 'expected'); + setText(e, expected); + report.appendChild(e); + + e = document.createElement('p'); + setText(e, 'Actual'); + report.appendChild(e); + + e = document.createElement('pre'); + e.setAttribute('class', 'actual'); + setText(e, actual); + report.appendChild(e); + } + + setText(document.getElementById('version'), esprima.version); + + window.setTimeout(function () { + var tick, context = getContext(esprima, reportCase, reportFailure); + + tick = new Date(); + testReflect(context.Reflect, context.Pattern); + tick = (new Date()) - tick; + + if (failures > 0) { + setText(document.getElementById('status'), total + ' tests. ' + + 'Failures: ' + failures + '. ' + tick + ' ms'); + } else { + setText(document.getElementById('status'), total + ' tests. ' + + 'No failure. ' + tick + ' ms'); + } + }, 513); + }; +} else { + (function (global) { + 'use strict'; + var esprima = require('../esprima'), + tick, + total = 0, + failures = [], + header, + current, + context; + + function reportCase(code) { + total += 1; + current = code; + } + + function reportFailure(expected, actual) { + failures.push({ + source: current, + expected: expected.toString(), + actual: actual.toString() + }); + } + + context = getContext(esprima, reportCase, reportFailure); + + tick = new Date(); + require('./reflect').testReflect(context.Reflect, context.Pattern); + tick = (new Date()) - tick; + + header = total + ' tests. ' + failures.length + ' failures. ' + + tick + ' ms'; + if (failures.length) { + console.error(header); + failures.forEach(function (failure) { + console.error(failure.source + ': Expected\n ' + + failure.expected.split('\n').join('\n ') + + '\nto match\n ' + failure.actual); + }); + } else { + console.log(header); + } + process.exit(failures.length === 0 ? 0 : 1); + }(this)); +} +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/reflect.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/reflect.js new file mode 100644 index 000000000..dba1ba8f1 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/reflect.js @@ -0,0 +1,422 @@ +// This is modified from Mozilla Reflect.parse test suite (the file is located +// at js/src/tests/js1_8_5/extensions/reflect-parse.js in the source tree). +// +// Some notable changes: +// * Removed unsupported features (destructuring, let, comprehensions...). +// * Removed tests for E4X (ECMAScript for XML). +// * Removed everything related to builder. +// * Enclosed every 'Pattern' construct with a scope. +// * Tweaked some expected tree to remove generator field. +// * Removed the test for bug 632030 and bug 632024. + +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +(function (exports) { + +function testReflect(Reflect, Pattern) { + +function program(elts) { return Pattern({ type: "Program", body: elts }) } +function exprStmt(expr) { return Pattern({ type: "ExpressionStatement", expression: expr }) } +function throwStmt(expr) { return Pattern({ type: "ThrowStatement", argument: expr }) } +function returnStmt(expr) { return Pattern({ type: "ReturnStatement", argument: expr }) } +function yieldExpr(expr) { return Pattern({ type: "YieldExpression", argument: expr }) } +function lit(val) { return Pattern({ type: "Literal", value: val }) } +var thisExpr = Pattern({ type: "ThisExpression" }); +function funDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration", + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }) } +function genFunDecl(id, params, body) { return Pattern({ type: "FunctionDeclaration", + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }) } +function declarator(id, init) { return Pattern({ type: "VariableDeclarator", id: id, init: init }) } +function varDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" }) } +function letDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" }) } +function constDecl(decls) { return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" }) } +function ident(name) { return Pattern({ type: "Identifier", name: name }) } +function dotExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: false, object: obj, property: id }) } +function memExpr(obj, id) { return Pattern({ type: "MemberExpression", computed: true, object: obj, property: id }) } +function forStmt(init, test, update, body) { return Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body }) } +function forInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false }) } +function forEachInStmt(lhs, rhs, body) { return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true }) } +function breakStmt(lab) { return Pattern({ type: "BreakStatement", label: lab }) } +function continueStmt(lab) { return Pattern({ type: "ContinueStatement", label: lab }) } +function blockStmt(body) { return Pattern({ type: "BlockStatement", body: body }) } +var emptyStmt = Pattern({ type: "EmptyStatement" }); +function ifStmt(test, cons, alt) { return Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons }) } +function labStmt(lab, stmt) { return Pattern({ type: "LabeledStatement", label: lab, body: stmt }) } +function withStmt(obj, stmt) { return Pattern({ type: "WithStatement", object: obj, body: stmt }) } +function whileStmt(test, stmt) { return Pattern({ type: "WhileStatement", test: test, body: stmt }) } +function doStmt(stmt, test) { return Pattern({ type: "DoWhileStatement", test: test, body: stmt }) } +function switchStmt(disc, cases) { return Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases }) } +function caseClause(test, stmts) { return Pattern({ type: "SwitchCase", test: test, consequent: stmts }) } +function defaultClause(stmts) { return Pattern({ type: "SwitchCase", test: null, consequent: stmts }) } +function catchClause(id, guard, body) { if (guard) { return Pattern({ type: "GuardedCatchClause", param: id, guard: guard, body: body }) } else { return Pattern({ type: "CatchClause", param: id, body: body }) } } +function tryStmt(body, guarded, catches, fin) { return Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handlers: catches, finalizer: fin }) } +function letStmt(head, body) { return Pattern({ type: "LetStatement", head: head, body: body }) } +function funExpr(id, args, body, gen) { return Pattern({ type: "FunctionExpression", + id: id, + params: args, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }) } +function genFunExpr(id, args, body) { return Pattern({ type: "FunctionExpression", + id: id, + params: args, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }) } + +function unExpr(op, arg) { return Pattern({ type: "UnaryExpression", operator: op, argument: arg, prefix: true }) } +function binExpr(op, left, right) { return Pattern({ type: "BinaryExpression", operator: op, left: left, right: right }) } +function aExpr(op, left, right) { return Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right }) } +function updExpr(op, arg, prefix) { return Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix }) } +function logExpr(op, left, right) { return Pattern({ type: "LogicalExpression", operator: op, left: left, right: right }) } + +function condExpr(test, cons, alt) { return Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt }) } +function seqExpr(exprs) { return Pattern({ type: "SequenceExpression", expressions: exprs }) } +function newExpr(callee, args) { return Pattern({ type: "NewExpression", callee: callee, arguments: args }) } +function callExpr(callee, args) { return Pattern({ type: "CallExpression", callee: callee, arguments: args }) } +function arrExpr(elts) { return Pattern({ type: "ArrayExpression", elements: elts }) } +function objExpr(elts) { return Pattern({ type: "ObjectExpression", properties: elts }) } +function objProp(key, value, kind) { return Pattern({ type: "Property", key: key, value: value, kind: kind }) } + +function arrPatt(elts) { return Pattern({ type: "ArrayPattern", elements: elts }) } +function objPatt(elts) { return Pattern({ type: "ObjectPattern", properties: elts }) } + +function localSrc(src) { return "(function(){ " + src + " })" } +function localPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([patt])))]) } +function blockSrc(src) { return "(function(){ { " + src + " } })" } +function blockPatt(patt) { return program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))]) } + +function assertBlockStmt(src, patt) { + blockPatt(patt).assert(Reflect.parse(blockSrc(src))); +} + +function assertBlockExpr(src, patt) { + assertBlockStmt(src, exprStmt(patt)); +} + +function assertBlockDecl(src, patt, builder) { + blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder})); +} + +function assertLocalStmt(src, patt) { + localPatt(patt).assert(Reflect.parse(localSrc(src))); +} + +function assertLocalExpr(src, patt) { + assertLocalStmt(src, exprStmt(patt)); +} + +function assertLocalDecl(src, patt) { + localPatt(patt).assert(Reflect.parse(localSrc(src))); +} + +function assertGlobalStmt(src, patt, builder) { + program([patt]).assert(Reflect.parse(src, {builder: builder})); +} + +function assertGlobalExpr(src, patt, builder) { + program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder})); + //assertStmt(src, exprStmt(patt)); +} + +function assertGlobalDecl(src, patt) { + program([patt]).assert(Reflect.parse(src)); +} + +function assertProg(src, patt) { + program(patt).assert(Reflect.parse(src)); +} + +function assertStmt(src, patt) { + assertLocalStmt(src, patt); + assertGlobalStmt(src, patt); + assertBlockStmt(src, patt); +} + +function assertExpr(src, patt) { + assertLocalExpr(src, patt); + assertGlobalExpr(src, patt); + assertBlockExpr(src, patt); +} + +function assertDecl(src, patt) { + assertLocalDecl(src, patt); + assertGlobalDecl(src, patt); + assertBlockDecl(src, patt); +} + +function assertError(src, errorType) { + try { + Reflect.parse(src); + } catch (e) { + return; + } + throw new Error("expected " + errorType.name + " for " + uneval(src)); +} + + +// general tests + +// NB: These are useful but for now jit-test doesn't do I/O reliably. + +//program(_).assert(Reflect.parse(snarf('data/flapjax.txt'))); +//program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt'))); +//program(_).assert(Reflect.parse(snarf('data/prototype.js'))); +//program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js'))); +//program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js'))); + + +// declarations + +assertDecl("var x = 1, y = 2, z = 3", + varDecl([declarator(ident("x"), lit(1)), + declarator(ident("y"), lit(2)), + declarator(ident("z"), lit(3))])); +assertDecl("var x, y, z", + varDecl([declarator(ident("x"), null), + declarator(ident("y"), null), + declarator(ident("z"), null)])); +assertDecl("function foo() { }", + funDecl(ident("foo"), [], blockStmt([]))); +assertDecl("function foo() { return 42 }", + funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))]))); + + +// Bug 591437: rebound args have their defs turned into uses +assertDecl("function f(a) { function a() { } }", + funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))]))); +assertDecl("function f(a,b,c) { function b() { } }", + funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))]))); + +// expressions + +assertExpr("true", lit(true)); +assertExpr("false", lit(false)); +assertExpr("42", lit(42)); +assertExpr("(/asdf/)", lit(/asdf/)); +assertExpr("this", thisExpr); +assertExpr("foo", ident("foo")); +assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar"))); +assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar"))); +assertExpr("(function(){})", funExpr(null, [], blockStmt([]))); +assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([]))); +assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([]))); +assertExpr("(++x)", updExpr("++", ident("x"), true)); +assertExpr("(x++)", updExpr("++", ident("x"), false)); +assertExpr("(+x)", unExpr("+", ident("x"))); +assertExpr("(-x)", unExpr("-", ident("x"))); +assertExpr("(!x)", unExpr("!", ident("x"))); +assertExpr("(~x)", unExpr("~", ident("x"))); +assertExpr("(delete x)", unExpr("delete", ident("x"))); +assertExpr("(typeof x)", unExpr("typeof", ident("x"))); +assertExpr("(void x)", unExpr("void", ident("x"))); +assertExpr("(x == y)", binExpr("==", ident("x"), ident("y"))); +assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y"))); +assertExpr("(x === y)", binExpr("===", ident("x"), ident("y"))); +assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y"))); +assertExpr("(x < y)", binExpr("<", ident("x"), ident("y"))); +assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y"))); +assertExpr("(x > y)", binExpr(">", ident("x"), ident("y"))); +assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y"))); +assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y"))); +assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y"))); +assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y"))); +assertExpr("(x + y)", binExpr("+", ident("x"), ident("y"))); +assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z"))); +assertExpr("(x - y)", binExpr("-", ident("x"), ident("y"))); +assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z"))); +assertExpr("(x * y)", binExpr("*", ident("x"), ident("y"))); +assertExpr("(x / y)", binExpr("/", ident("x"), ident("y"))); +assertExpr("(x % y)", binExpr("%", ident("x"), ident("y"))); +assertExpr("(x | y)", binExpr("|", ident("x"), ident("y"))); +assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y"))); +assertExpr("(x & y)", binExpr("&", ident("x"), ident("y"))); +assertExpr("(x in y)", binExpr("in", ident("x"), ident("y"))); +assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y"))); +assertExpr("(x = y)", aExpr("=", ident("x"), ident("y"))); +assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y"))); +assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y"))); +assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y"))); +assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y"))); +assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y"))); +assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y"))); +assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y"))); +assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y"))); +assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y"))); +assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y"))); +assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y"))); +assertExpr("(x || y)", logExpr("||", ident("x"), ident("y"))); +assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y"))); +assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z"))) +assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z"))); +assertExpr("(x,y)", seqExpr([ident("x"),ident("y")])) +assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")])) +assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")])); +assertExpr("(new Object)", newExpr(ident("Object"), [])); +assertExpr("(new Object())", newExpr(ident("Object"), [])); +assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)])); +assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)])); +assertExpr("(String())", callExpr(ident("String"), [])); +assertExpr("(String(42))", callExpr(ident("String"), [lit(42)])); +assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)])); +assertExpr("[]", arrExpr([])); +assertExpr("[1]", arrExpr([lit(1)])); +assertExpr("[1,2]", arrExpr([lit(1),lit(2)])); +assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)])); +assertExpr("[1,,2,3]", arrExpr([lit(1),,lit(2),lit(3)])); +assertExpr("[1,,,2,3]", arrExpr([lit(1),,,lit(2),lit(3)])); +assertExpr("[1,,,2,,3]", arrExpr([lit(1),,,lit(2),,lit(3)])); +assertExpr("[1,,,2,,,3]", arrExpr([lit(1),,,lit(2),,,lit(3)])); +assertExpr("[,1,2,3]", arrExpr([,lit(1),lit(2),lit(3)])); +assertExpr("[,,1,2,3]", arrExpr([,,lit(1),lit(2),lit(3)])); +assertExpr("[,,,1,2,3]", arrExpr([,,,lit(1),lit(2),lit(3)])); +assertExpr("[,,,1,2,3,]", arrExpr([,,,lit(1),lit(2),lit(3)])); +assertExpr("[,,,1,2,3,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined])); +assertExpr("[,,,1,2,3,,,]", arrExpr([,,,lit(1),lit(2),lit(3),undefined,undefined])); +assertExpr("[,,,,,]", arrExpr([undefined,undefined,undefined,undefined,undefined])); +assertExpr("({})", objExpr([])); +assertExpr("({x:1})", objExpr([objProp(ident("x"), lit(1), "init")])); +assertExpr("({x:1, y:2})", objExpr([objProp(ident("x"), lit(1), "init"), + objProp(ident("y"), lit(2), "init")])); +assertExpr("({x:1, y:2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"), + objProp(ident("y"), lit(2), "init"), + objProp(ident("z"), lit(3), "init") ])); +assertExpr("({x:1, 'y':2, z:3})", objExpr([objProp(ident("x"), lit(1), "init"), + objProp(lit("y"), lit(2), "init"), + objProp(ident("z"), lit(3), "init") ])); +assertExpr("({'x':1, 'y':2, z:3})", objExpr([objProp(lit("x"), lit(1), "init"), + objProp(lit("y"), lit(2), "init"), + objProp(ident("z"), lit(3), "init") ])); +assertExpr("({'x':1, 'y':2, 3:3})", objExpr([objProp(lit("x"), lit(1), "init"), + objProp(lit("y"), lit(2), "init"), + objProp(lit(3), lit(3), "init") ])); + +// Bug 571617: eliminate constant-folding +assertExpr("2 + 3", binExpr("+", lit(2), lit(3))); + +// Bug 632026: constant-folding +assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a")))); + +// Bug 632056: constant-folding +program([exprStmt(ident("f")), + ifStmt(lit(1), + funDecl(ident("f"), [], blockStmt([])), + null)]).assert(Reflect.parse("f; if (1) function f(){}")); + +// statements + +assertStmt("throw 42", throwStmt(lit(42))); +assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null))); +assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null))); +assertStmt("for (var x; y; z) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), ident("z"), breakStmt(null))); +assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), ident("y"), ident("z"), breakStmt(null))); +assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null))); +assertStmt("for (var x; ; z) break", forStmt(varDecl([declarator(ident("x"), null)]), null, ident("z"), breakStmt(null))); +assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([declarator(ident("x"), lit(42))]), null, ident("z"), breakStmt(null))); +assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null))); +assertStmt("for (var x; y; ) break", forStmt(varDecl([declarator(ident("x"), null)]), ident("y"), null, breakStmt(null))); +assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([declarator(ident("x"),lit(42))]), ident("y"), null, breakStmt(null))); +assertStmt("for (var x in y) break", forInStmt(varDecl([declarator(ident("x"),null)]), ident("y"), breakStmt(null))); +assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null))); +assertStmt("{ }", blockStmt([])); +assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))])); +assertStmt(";", emptyStmt); +assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null)); +assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true)))); +assertStmt("if (foo) { throw 1; throw 2; throw 3; }", + ifStmt(ident("foo"), + blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]), + null)); +assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;", + ifStmt(ident("foo"), + blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]), + exprStmt(lit(true)))); +assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo"))))); +assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo"))))); +assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([]))); +assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))]))); +assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([]))); +assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))]))); +assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo"))); +assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo"))); +assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }", + switchStmt(ident("foo"), + [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]), + caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]), + defaultClause([ exprStmt(lit(3)) ]) ])); +assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }", + switchStmt(ident("foo"), + [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]), + caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]), + defaultClause([ exprStmt(lit(3)) ]), + caseClause(lit(42), [ exprStmt(lit(42)) ]) ])); +assertStmt("try { } catch (e) { }", + tryStmt(blockStmt([]), + [], + [ catchClause(ident("e"), null, blockStmt([])) ], + null)); +assertStmt("try { } catch (e) { } finally { }", + tryStmt(blockStmt([]), + [], + [ catchClause(ident("e"), null, blockStmt([])) ], + blockStmt([]))); +assertStmt("try { } finally { }", + tryStmt(blockStmt([]), + [], + [], + blockStmt([]))); + +// redeclarations (TOK_NAME nodes with lexdef) + +assertStmt("function f() { function g() { } function g() { } }", + funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])), + funDecl(ident("g"), [], blockStmt([]))]))); + +assertStmt("function f() { function g() { } function g() { return 42 } }", + funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])), + funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))]))); + +assertStmt("function f() { var x = 42; var x = 43; }", + funDecl(ident("f"), [], blockStmt([varDecl([declarator(ident("x"),lit(42))]), + varDecl([declarator(ident("x"),lit(43))])]))); + +// getters and setters + + assertExpr("({ get x() { return 42 } })", + objExpr([ objProp(ident("x"), + funExpr(null, [], blockStmt([returnStmt(lit(42))])), + "get" ) ])); + assertExpr("({ set x(v) { return 42 } })", + objExpr([ objProp(ident("x"), + funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])), + "set" ) ])); + +} + +exports.testReflect = testReflect; + +}(typeof exports === 'undefined' ? this : exports)); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/run.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/run.js new file mode 100644 index 000000000..32ca3faa4 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/run.js @@ -0,0 +1,66 @@ +/* + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint node:true */ + +(function () { + 'use strict'; + + var child = require('child_process'), + nodejs = '"' + process.execPath + '"', + ret = 0, + suites, + index; + + suites = [ + 'runner', + 'compat' + ]; + + function nextTest() { + var suite = suites[index]; + + if (index < suites.length) { + child.exec(nodejs + ' ./test/' + suite + '.js', function (err, stdout, stderr) { + if (stdout) { + process.stdout.write(suite + ': ' + stdout); + } + if (stderr) { + process.stderr.write(suite + ': ' + stderr); + } + if (err) { + ret = err.code; + } + index += 1; + nextTest(); + }); + } else { + process.exit(ret); + } + } + + index = 0; + nextTest(); +}()); diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/runner.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/runner.js new file mode 100644 index 000000000..c1a3fc9bf --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/runner.js @@ -0,0 +1,387 @@ +/* + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + Copyright (C) 2011 Yusuke Suzuki + Copyright (C) 2011 Arpad Borsos + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +/*jslint browser:true node:true */ +/*global esprima:true, testFixture:true */ + +var runTests; + +// Special handling for regular expression literal since we need to +// convert it to a string literal, otherwise it will be decoded +// as object "{}" and the regular expression would be lost. +function adjustRegexLiteral(key, value) { + 'use strict'; + if (key === 'value' && value instanceof RegExp) { + value = value.toString(); + } + return value; +} + +function NotMatchingError(expected, actual) { + 'use strict'; + Error.call(this, 'Expected '); + this.expected = expected; + this.actual = actual; +} +NotMatchingError.prototype = new Error(); + +function errorToObject(e) { + 'use strict'; + var msg = e.toString(); + + // Opera 9.64 produces an non-standard string in toString(). + if (msg.substr(0, 6) !== 'Error:') { + if (typeof e.message === 'string') { + msg = 'Error: ' + e.message; + } + } + + return { + index: e.index, + lineNumber: e.lineNumber, + column: e.column, + message: msg + }; +} + +function testParse(esprima, code, syntax) { + 'use strict'; + var expected, tree, actual, options, StringObject, i, len, err; + + // alias, so that JSLint does not complain. + StringObject = String; + + options = { + comment: (typeof syntax.comments !== 'undefined'), + range: true, + loc: true, + tokens: (typeof syntax.tokens !== 'undefined'), + raw: true, + tolerant: (typeof syntax.errors !== 'undefined') + }; + + if (typeof syntax.tokens !== 'undefined') { + if (syntax.tokens.length > 0) { + options.range = (typeof syntax.tokens[0].range !== 'undefined'); + options.loc = (typeof syntax.tokens[0].loc !== 'undefined'); + } + } + + if (typeof syntax.comments !== 'undefined') { + if (syntax.comments.length > 0) { + options.range = (typeof syntax.comments[0].range !== 'undefined'); + options.loc = (typeof syntax.comments[0].loc !== 'undefined'); + } + } + + expected = JSON.stringify(syntax, null, 4); + try { + tree = esprima.parse(code, options); + tree = (options.comment || options.tokens || options.tolerant) ? tree : tree.body[0]; + + if (options.tolerant) { + for (i = 0, len = tree.errors.length; i < len; i += 1) { + tree.errors[i] = errorToObject(tree.errors[i]); + } + } + + actual = JSON.stringify(tree, adjustRegexLiteral, 4); + + // Only to ensure that there is no error when using string object. + esprima.parse(new StringObject(code), options); + + } catch (e) { + throw new NotMatchingError(expected, e.toString()); + } + if (expected !== actual) { + throw new NotMatchingError(expected, actual); + } + + function filter(key, value) { + if (key === 'value' && value instanceof RegExp) { + value = value.toString(); + } + return (key === 'loc' || key === 'range') ? undefined : value; + } + + if (options.tolerant) { + return; + } + + + // Check again without any location info. + options.range = false; + options.loc = false; + expected = JSON.stringify(syntax, filter, 4); + try { + tree = esprima.parse(code, options); + tree = (options.comment || options.tokens) ? tree : tree.body[0]; + + if (options.tolerant) { + for (i = 0, len = tree.errors.length; i < len; i += 1) { + tree.errors[i] = errorToObject(tree.errors[i]); + } + } + + actual = JSON.stringify(tree, filter, 4); + } catch (e) { + throw new NotMatchingError(expected, e.toString()); + } + if (expected !== actual) { + throw new NotMatchingError(expected, actual); + } +} + +function testError(esprima, code, exception) { + 'use strict'; + var i, options, expected, actual, handleInvalidRegexFlag; + + // Different parsing options should give the same error. + options = [ + {}, + { comment: true }, + { raw: true }, + { raw: true, comment: true } + ]; + + // If handleInvalidRegexFlag is true, an invalid flag in a regular expression + // will throw an exception. In some old version V8, this is not the case + // and hence handleInvalidRegexFlag is false. + handleInvalidRegexFlag = false; + try { + 'test'.match(new RegExp('[a-z]', 'x')); + } catch (e) { + handleInvalidRegexFlag = true; + } + + expected = JSON.stringify(exception); + + for (i = 0; i < options.length; i += 1) { + + try { + esprima.parse(code, options[i]); + } catch (e) { + actual = JSON.stringify(errorToObject(e)); + } + + if (expected !== actual) { + + // Compensate for old V8 which does not handle invalid flag. + if (exception.message.indexOf('Invalid regular expression') > 0) { + if (typeof actual === 'undefined' && !handleInvalidRegexFlag) { + return; + } + } + + throw new NotMatchingError(expected, actual); + } + + } +} + +function testAPI(esprima, code, result) { + 'use strict'; + var expected, res, actual; + + expected = JSON.stringify(result.result, null, 4); + try { + if (typeof result.property !== 'undefined') { + res = esprima[result.property]; + } else { + res = esprima[result.call].apply(esprima, result.args); + } + actual = JSON.stringify(res, adjustRegexLiteral, 4); + } catch (e) { + throw new NotMatchingError(expected, e.toString()); + } + if (expected !== actual) { + throw new NotMatchingError(expected, actual); + } +} + +function runTest(esprima, code, result) { + 'use strict'; + if (result.hasOwnProperty('lineNumber')) { + testError(esprima, code, result); + } else if (result.hasOwnProperty('result')) { + testAPI(esprima, code, result); + } else { + testParse(esprima, code, result); + } +} + +if (typeof window !== 'undefined') { + // Run all tests in a browser environment. + runTests = function () { + 'use strict'; + var total = 0, + failures = 0, + category, + fixture, + source, + tick, + expected, + index, + len; + + function setText(el, str) { + if (typeof el.innerText === 'string') { + el.innerText = str; + } else { + el.textContent = str; + } + } + + function startCategory(category) { + var report, e; + report = document.getElementById('report'); + e = document.createElement('h4'); + setText(e, category); + report.appendChild(e); + } + + function reportSuccess(code) { + var report, e; + report = document.getElementById('report'); + e = document.createElement('pre'); + e.setAttribute('class', 'code'); + setText(e, code); + report.appendChild(e); + } + + function reportFailure(code, expected, actual) { + var report, e; + + report = document.getElementById('report'); + + e = document.createElement('p'); + setText(e, 'Code:'); + report.appendChild(e); + + e = document.createElement('pre'); + e.setAttribute('class', 'code'); + setText(e, code); + report.appendChild(e); + + e = document.createElement('p'); + setText(e, 'Expected'); + report.appendChild(e); + + e = document.createElement('pre'); + e.setAttribute('class', 'expected'); + setText(e, expected); + report.appendChild(e); + + e = document.createElement('p'); + setText(e, 'Actual'); + report.appendChild(e); + + e = document.createElement('pre'); + e.setAttribute('class', 'actual'); + setText(e, actual); + report.appendChild(e); + } + + setText(document.getElementById('version'), esprima.version); + + tick = new Date(); + for (category in testFixture) { + if (testFixture.hasOwnProperty(category)) { + startCategory(category); + fixture = testFixture[category]; + for (source in fixture) { + if (fixture.hasOwnProperty(source)) { + expected = fixture[source]; + total += 1; + try { + runTest(esprima, source, expected); + reportSuccess(source, JSON.stringify(expected, null, 4)); + } catch (e) { + failures += 1; + reportFailure(source, e.expected, e.actual); + } + } + } + } + } + tick = (new Date()) - tick; + + if (failures > 0) { + setText(document.getElementById('status'), total + ' tests. ' + + 'Failures: ' + failures + '. ' + tick + ' ms'); + } else { + setText(document.getElementById('status'), total + ' tests. ' + + 'No failure. ' + tick + ' ms'); + } + }; +} else { + (function () { + 'use strict'; + + var esprima = require('../esprima'), + vm = require('vm'), + fs = require('fs'), + total = 0, + failures = [], + tick = new Date(), + expected, + header; + + vm.runInThisContext(fs.readFileSync(__dirname + '/test.js', 'utf-8')); + + Object.keys(testFixture).forEach(function (category) { + Object.keys(testFixture[category]).forEach(function (source) { + total += 1; + expected = testFixture[category][source]; + try { + runTest(esprima, source, expected); + } catch (e) { + e.source = source; + failures.push(e); + } + }); + }); + tick = (new Date()) - tick; + + header = total + ' tests. ' + failures.length + ' failures. ' + + tick + ' ms'; + if (failures.length) { + console.error(header); + failures.forEach(function (failure) { + console.error(failure.source + ': Expected\n ' + + failure.expected.split('\n').join('\n ') + + '\nto match\n ' + failure.actual); + }); + } else { + console.log(header); + } + process.exit(failures.length === 0 ? 0 : 1); + }()); +} diff --git a/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/test.js b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/test.js new file mode 100644 index 000000000..8ceee54b7 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/node_modules/esprima/test/test.js @@ -0,0 +1,20238 @@ +/* + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + Copyright (C) 2011 Yusuke Suzuki + Copyright (C) 2011 Arpad Borsos + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 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. +*/ + +var testFixture = { + + 'Primary Expression': { + + 'this\n': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'ThisExpression', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 0 } + } + }], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 0 } + }, + tokens: [{ + type: 'Keyword', + value: 'this', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }] + }, + + 'null\n': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: null, + raw: 'null', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 0 } + } + }], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 0 } + }, + tokens: [{ + type: 'Null', + value: 'null', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }] + }, + + '\n 42\n\n': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }, + range: [5, 9], + loc: { + start: { line: 2, column: 4 }, + end: { line: 4, column: 0 } + } + }], + range: [5, 9], + loc: { + start: { line: 2, column: 4 }, + end: { line: 4, column: 0 } + }, + tokens: [{ + type: 'Numeric', + value: '42', + range: [5, 7], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }] + }, + + '(1 + 2 ) * 3': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Literal', + value: 1, + raw: '1', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'Literal', + value: 2, + raw: '2', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [1, 6], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Literal', + value: 3, + raw: '3', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + + }, + + 'Grouping Operator': { + + '(1) + (2 ) + 3': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Literal', + value: 1, + raw: '1', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'Literal', + value: 2, + raw: '2', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + right: { + type: 'Literal', + value: 3, + raw: '3', + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + '4 + 5 << (6)': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<<', + left: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Literal', + value: 4, + raw: '4', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 5, + raw: '5', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Literal', + value: 6, + raw: '6', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + + }, + + 'Array Initializer': { + + 'x = []': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }], + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + }, + tokens: [{ + type: 'Identifier', + value: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, { + type: 'Punctuator', + value: '=', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Punctuator', + value: '[', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: ']', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }] + }, + + 'x = [ ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x = [ 42 ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [{ + type: 'Literal', + value: 42, + raw: '42', + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }], + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + + 'x = [ 42, ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [{ + type: 'Literal', + value: 42, + raw: '42', + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }], + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'x = [ ,, 42 ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [ + null, + null, + { + type: 'Literal', + value: 42, + raw: '42', + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }], + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'x = [ 1, 2, 3, ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [{ + type: 'Literal', + value: 1, + raw: '1', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'Literal', + value: 2, + raw: '2', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, { + type: 'Literal', + value: 3, + raw: '3', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }], + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + 'x = [ 1, 2,, 3, ]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ArrayExpression', + elements: [{ + type: 'Literal', + value: 1, + raw: '1', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'Literal', + value: 2, + raw: '2', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, null, { + type: 'Literal', + value: 3, + raw: '3', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + '日本語 = []': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: '日本語', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'T\u203F = []': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'T\u203F', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'T\u200C = []': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'T\u200C', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'T\u200D = []': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'T\u200D', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '\u2163\u2161 = []': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: '\u2163\u2161', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '\u2163\u2161\u200A=\u2009[]': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: '\u2163\u2161', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + + }, + + 'Object Initializer': { + + 'x = {}': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [], + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x = { }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x = { answer: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'answer', + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [14, 16], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 16 } + } + }, + kind: 'init', + range: [6, 16], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 16 } + } + }], + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + + 'x = { if: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'if', + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + kind: 'init', + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }], + range: [4, 14], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + 'x = { true: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'true', + range: [6, 10], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + kind: 'init', + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }], + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + 'x = { false: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'false', + range: [6, 11], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 11 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [13, 15], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 15 } + } + }, + kind: 'init', + range: [6, 15], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 15 } + } + }], + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + 'x = { null: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'null', + range: [6, 10], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + kind: 'init', + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }], + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + 'x = { "answer": 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 'answer', + raw: '"answer"', + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [16, 18], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 18 } + } + }, + kind: 'init', + range: [6, 18], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 18 } + } + }], + range: [4, 20], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + + 'x = { x: 1, x: 2 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [ + { + type: 'Property', + key: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + value: { + type: 'Literal', + value: 1, + raw: '1', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + kind: 'init', + range: [6, 10], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'x', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + value: { + type: 'Literal', + value: 2, + raw: '2', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + kind: 'init', + range: [12, 16], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 16 } + } + } + ], + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + + 'x = { get width() { return m_width } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'width', + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ReturnStatement', + argument: { + type: 'Identifier', + name: 'm_width', + range: [27, 34], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 34 } + } + }, + range: [20, 35], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 35 } + } + }], + range: [18, 36], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 36], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 36 } + } + }, + kind: 'get', + range: [6, 36], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 36 } + } + }], + range: [4, 38], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 38 } + } + }, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + + 'x = { get undef() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'undef', + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + kind: 'get', + range: [6, 20], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 20 } + } + }], + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + + 'x = { get if() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'if', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + kind: 'get', + range: [6, 17], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 17 } + } + }], + range: [4, 19], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + + 'x = { get true() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'true', + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [17, 19], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 19 } + } + }, + rest: null, + generator: false, + expression: false, + range: [17, 19], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 19 } + } + }, + kind: 'get', + range: [6, 19], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + }], + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + + 'x = { get false() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'false', + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + kind: 'get', + range: [6, 20], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 20 } + } + }], + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + + 'x = { get null() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'null', + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [17, 19], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 19 } + } + }, + rest: null, + generator: false, + expression: false, + range: [17, 19], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 19 } + } + }, + kind: 'get', + range: [6, 19], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + }], + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + + 'x = { get "undef"() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 'undef', + raw: '"undef"', + range: [10, 17], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 17 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [20, 22], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 22 } + } + }, + rest: null, + generator: false, + expression: false, + range: [20, 22], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 22 } + } + }, + kind: 'get', + range: [6, 22], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 22 } + } + }], + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'x = { get 10() {} }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 10, + raw: '10', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + kind: 'get', + range: [6, 17], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 17 } + } + }], + range: [4, 19], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + + 'x = { set width(w) { m_width = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'width', + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_width', + range: [21, 28], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 28 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [31, 32], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 32 } + } + }, + range: [21, 32], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 32 } + } + }, + range: [21, 33], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 33 } + } + }], + range: [19, 34], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [19, 34], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 34 } + } + }, + kind: 'set', + range: [6, 34], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 34 } + } + }], + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'x = { set if(w) { m_if = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'if', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_if', + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + range: [18, 26], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 26 } + } + }, + range: [18, 27], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 27 } + } + }], + range: [16, 28], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 28 } + } + }, + rest: null, + generator: false, + expression: false, + range: [16, 28], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 28 } + } + }, + kind: 'set', + range: [6, 28], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 28 } + } + }], + range: [4, 30], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 30 } + } + }, + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + + 'x = { set true(w) { m_true = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'true', + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_true', + range: [20, 26], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 26 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 30], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }], + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + kind: 'set', + range: [6, 32], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 32 } + } + }], + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + + 'x = { set false(w) { m_false = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'false', + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_false', + range: [21, 28], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 28 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [31, 32], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 32 } + } + }, + range: [21, 32], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 32 } + } + }, + range: [21, 33], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 33 } + } + }], + range: [19, 34], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [19, 34], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 34 } + } + }, + kind: 'set', + range: [6, 34], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 34 } + } + }], + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'x = { set null(w) { m_null = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'null', + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_null', + range: [20, 26], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 26 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 30], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }], + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + kind: 'set', + range: [6, 32], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 32 } + } + }], + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + + 'x = { set "null"(w) { m_null = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 'null', + raw: '"null"', + range: [10, 16], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 16 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_null', + range: [22, 28], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 28 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [31, 32], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 32 } + } + }, + range: [22, 32], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 32 } + } + }, + range: [22, 33], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 33 } + } + }], + range: [20, 34], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [20, 34], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 34 } + } + }, + kind: 'set', + range: [6, 34], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 34 } + } + }], + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'x = { set 10(w) { m_null = w } }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 10, + raw: '10', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'w', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'm_null', + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + right: { + type: 'Identifier', + name: 'w', + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + range: [18, 28], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 28 } + } + }, + range: [18, 29], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 29 } + } + }], + range: [16, 30], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 30 } + } + }, + rest: null, + generator: false, + expression: false, + range: [16, 30], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 30 } + } + }, + kind: 'set', + range: [6, 30], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 30 } + } + }], + range: [4, 32], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 32 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + + 'x = { get: 42 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'get', + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [11, 13], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + kind: 'init', + range: [6, 13], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 13 } + } + }], + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + 'x = { set: 43 }': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'set', + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + value: { + type: 'Literal', + value: 43, + raw: '43', + range: [11, 13], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + kind: 'init', + range: [6, 13], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 13 } + } + }], + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + + }, + + 'Comments': { + + '/* block comment */ 42': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [20, 22], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 22 } + } + }, + range: [20, 22], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 22 } + } + }, + + '42 /*The*/ /*Answer*/': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + }, + comments: [{ + type: 'Block', + value: 'The', + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } + } + }, { + type: 'Block', + value: 'Answer', + range: [11, 21], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 21 } + } + }] + }, + + '42 /*the*/ /*answer*/': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [0, 2] + }, + range: [0, 21] + }], + range: [0, 21], + comments: [{ + type: 'Block', + value: 'the', + range: [3, 10] + }, { + type: 'Block', + value: 'answer', + range: [11, 21] + }] + }, + + '/* multiline\ncomment\nshould\nbe\nignored */ 42': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [42, 44], + loc: { + start: { line: 5, column: 11 }, + end: { line: 5, column: 13 } + } + }, + range: [42, 44], + loc: { + start: { line: 5, column: 11 }, + end: { line: 5, column: 13 } + } + }, + + '/*a\r\nb*/ 42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [9, 11], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }, + range: [9, 11], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }], + range: [9, 11], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + }, + comments: [{ + type: 'Block', + value: 'a\r\nb', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 3 } + } + }] + }, + + '/*a\rb*/ 42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }, + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }], + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + }, + comments: [{ + type: 'Block', + value: 'a\rb', + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 3 } + } + }] + }, + + '/*a\nb*/ 42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }, + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }], + range: [8, 10], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + }, + comments: [{ + type: 'Block', + value: 'a\nb', + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 3 } + } + }] + }, + + '/*a\nc*/ 42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }, + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + } + }], + loc: { + start: { line: 2, column: 4 }, + end: { line: 2, column: 6 } + }, + comments: [{ + type: 'Block', + value: 'a\nc', + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 3 } + } + }] + }, + + '// line comment\n42': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [16, 18], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }, + range: [16, 18], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }, + + '42 // line comment': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + }, + comments: [{ + type: 'Line', + value: ' line comment', + range: [3, 18], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 18 } + } + }] + }, + + '// Hello, world!\n42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [17, 19], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }, + range: [17, 19], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }], + range: [17, 19], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + }, + comments: [{ + type: 'Line', + value: ' Hello, world!', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }] + }, + + '// Hello, world!\n': { + type: 'Program', + body: [], + range: [17, 17], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 0 } + }, + comments: [{ + type: 'Line', + value: ' Hello, world!', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }] + }, + + '// Hallo, world!\n': { + type: 'Program', + body: [], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 0 } + }, + comments: [{ + type: 'Line', + value: ' Hallo, world!', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }] + }, + + '//\n42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [3, 5], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }, + range: [3, 5], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }], + range: [3, 5], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + }, + comments: [{ + type: 'Line', + value: '', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }] + }, + + '//': { + type: 'Program', + body: [], + range: [2, 2], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 2 } + }, + comments: [{ + type: 'Line', + value: '', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }] + }, + + '// ': { + type: 'Program', + body: [], + range: [3, 3], + comments: [{ + type: 'Line', + value: ' ', + range: [0, 3] + }] + }, + + '/**/42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }], + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + }, + comments: [{ + type: 'Block', + value: '', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }] + }, + + '// Hello, world!\n\n// Another hello\n42': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [37, 39], + loc: { + start: { line: 4, column: 0 }, + end: { line: 4, column: 2 } + } + }, + range: [37, 39], + loc: { + start: { line: 4, column: 0 }, + end: { line: 4, column: 2 } + } + }], + range: [37, 39], + loc: { + start: { line: 4, column: 0 }, + end: { line: 4, column: 2 } + }, + comments: [{ + type: 'Line', + value: ' Hello, world!', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, { + type: 'Line', + value: ' Another hello', + range: [18, 36], + loc: { + start: { line: 3, column: 0 }, + end: { line: 3, column: 18 } + } + }] + }, + + 'if (x) { // Some comment\ndoThat(); }': { + type: 'Program', + body: [{ + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + consequent: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doThat', + range: [25, 31], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }, + 'arguments': [], + range: [25, 33], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 8 } + } + }, + range: [25, 34], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 9 } + } + }], + range: [7, 36], + loc: { + start: { line: 1, column: 7 }, + end: { line: 2, column: 11 } + } + }, + alternate: null, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 11 } + } + }], + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 11 } + }, + comments: [{ + type: 'Line', + value: ' Some comment', + range: [9, 24], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 24 } + } + }] + }, + + 'switch (answer) { case 42: /* perfect */ bingo() }': { + type: 'Program', + body: [{ + type: 'SwitchStatement', + discriminant: { + type: 'Identifier', + name: 'answer', + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + cases: [{ + type: 'SwitchCase', + test: { + type: 'Literal', + value: 42, + raw: '42', + range: [23, 25], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 25 } + } + }, + consequent: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'bingo', + range: [41, 46], + loc: { + start: { line: 1, column: 41 }, + end: { line: 1, column: 46 } + } + }, + 'arguments': [], + range: [41, 48], + loc: { + start: { line: 1, column: 41 }, + end: { line: 1, column: 48 } + } + }, + range: [41, 49], + loc: { + start: { line: 1, column: 41 }, + end: { line: 1, column: 49 } + } + }], + range: [18, 49], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 49 } + } + }], + range: [0, 50], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 50 } + } + }], + range: [0, 50], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 50 } + }, + comments: [{ + type: 'Block', + value: ' perfect ', + range: [27, 40], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 40 } + } + }] + } + + }, + + 'Numeric Literals': { + + '0': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0, + raw: '0', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + + '42': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42, + raw: '42', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + '3': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 3, + raw: '3', + range: [0, 1] + }, + range: [0, 1] + }], + range: [0, 1], + tokens: [{ + type: 'Numeric', + value: '3', + range: [0, 1] + }] + }, + + '5': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 5, + raw: '5', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + }, + tokens: [{ + type: 'Numeric', + value: '5', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }] + }, + + '.14': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0.14, + raw: '.14', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + '3.14159': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 3.14159, + raw: '3.14159', + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '6.02214179e+23': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 6.02214179e+23, + raw: '6.02214179e+23', + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + '1.492417830e-10': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 1.49241783e-10, + raw: '1.492417830e-10', + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + '0x0': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0, + raw: '0x0', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + '0e+100': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0, + raw: '0e+100', + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + '0xabc': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0xabc, + raw: '0xabc', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + '0xdef': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0xdef, + raw: '0xdef', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + '0X1A': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0x1A, + raw: '0X1A', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + + '0x10': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0x10, + raw: '0x10', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + + '0x100': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0x100, + raw: '0x100', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + '0X04': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 0X04, + raw: '0X04', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + + '02': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 2, + raw: '02', + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + '012': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 10, + raw: '012', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + '0012': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 10, + raw: '0012', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + } + + }, + + 'String Literals': { + + '"Hello"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello', + raw: '"Hello"', + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '"\\n\\r\\t\\v\\b\\f\\\\\\\'\\"\\0"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: '\n\r\t\x0B\b\f\\\'"\x00', + raw: '"\\n\\r\\t\\v\\b\\f\\\\\\\'\\"\\0"', + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + + '"\\u0061"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'a', + raw: '"\\u0061"', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + '"\\x61"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'a', + raw: '"\\x61"', + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + '"\\u00"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'u00', + raw: '"\\u00"', + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + '"\\xt"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'xt', + raw: '"\\xt"', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + '"Hello\\nworld"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\nworld', + raw: '"Hello\\nworld"', + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + '"Hello\\\nworld"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Helloworld', + raw: '"Hello\\\nworld"', + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 14 } + } + }, + + '"Hello\\02World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u0002World', + raw: '"Hello\\02World"', + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + '"Hello\\012World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u000AWorld', + raw: '"Hello\\012World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\122World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\122World', + raw: '"Hello\\122World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\0122World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u000A2World', + raw: '"Hello\\0122World"', + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + '"Hello\\312World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u00CAWorld', + raw: '"Hello\\312World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\412World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\412World', + raw: '"Hello\\412World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\812World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello812World', + raw: '"Hello\\812World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\712World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\712World', + raw: '"Hello\\712World"', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '"Hello\\0World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u0000World', + raw: '"Hello\\0World"', + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + '"Hello\\\r\nworld"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Helloworld', + raw: '"Hello\\\r\nworld"', + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 15 } + } + }, + + '"Hello\\1World"': { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'Hello\u0001World', + raw: '"Hello\\1World"', + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + }, + + 'Regular Expression Literals': { + + 'var x = /[a-z]/i': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/[a-z]/i', + raw: '/[a-z]/i', + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }], + kind: 'var', + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }], + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[a-z]/i', + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }] + }, + + 'var x = /[x-z]/i': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5] + }, + init: { + type: 'Literal', + value: '/[x-z]/i', + raw: '/[x-z]/i', + range: [8, 16] + }, + range: [4, 16] + }], + kind: 'var', + range: [0, 16] + }], + range: [0, 16], + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3] + }, { + type: 'Identifier', + value: 'x', + range: [4, 5] + }, { + type: 'Punctuator', + value: '=', + range: [6, 7] + }, { + type: 'RegularExpression', + value: '/[x-z]/i', + range: [8, 16] + }] + }, + + 'var x = /[a-c]/i': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/[a-c]/i', + raw: '/[a-c]/i', + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }], + kind: 'var', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[a-c]/i', + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }] + }, + + 'var x = /[P QR]/i': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/[P QR]/i', + raw: '/[P QR]/i', + range: [8, 17], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }], + kind: 'var', + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }], + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[P QR]/i', + range: [8, 17], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 17 } + } + }] + }, + + 'var x = /[\\]/]/': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: new RegExp('[\\]/]').toString(), + raw: '/[\\]/]/', + range: [8, 15], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }], + kind: 'var', + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }], + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[\\]/]/', + range: [8, 15], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 15 } + } + }] + }, + + 'var x = /foo\\/bar/': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/foo\\/bar/', + raw: '/foo\\/bar/', + range: [8, 18], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 18 } + } + }, + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }], + kind: 'var', + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/foo\\/bar/', + range: [8, 18], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 18 } + } + }] + }, + + 'var x = /=([^=\\s])+/g': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/=([^=\\s])+/g', + raw: '/=([^=\\s])+/g', + range: [8, 21], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 21 } + } + }, + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }], + kind: 'var', + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/=([^=\\s])+/g', + range: [8, 21], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 21 } + } + }] + }, + + 'var x = /[P QR]/\\u0067': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/[P QR]/g', + raw: '/[P QR]/\\u0067', + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }, + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }], + kind: 'var', + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }], + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[P QR]/\\u0067', + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }] + }, + + 'var x = /[P QR]/\\g': { + type: 'Program', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: '/[P QR]/g', + raw: '/[P QR]/\\g', + range: [8, 18], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 18 } + } + }, + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }], + kind: 'var', + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + }, + tokens: [{ + type: 'Keyword', + value: 'var', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, { + type: 'Identifier', + value: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'Punctuator', + value: '=', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, { + type: 'RegularExpression', + value: '/[P QR]/\\g', + range: [8, 18], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 18 } + } + }] + } + + }, + + 'Left-Hand-Side Expression': { + + 'new Button': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'Button', + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, + 'arguments': [], + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + + 'new Button()': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'Button', + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, + 'arguments': [], + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + + 'new new foo': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + 'arguments': [], + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + 'arguments': [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'new new foo()': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + 'arguments': [], + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, + 'arguments': [], + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'new foo().bar()': { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'MemberExpression', + computed: false, + object: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + 'arguments': [], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + property: { + type: 'Identifier', + name: 'bar', + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + 'arguments': [], + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + 'new foo[bar]': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'MemberExpression', + computed: true, + object: { + type: 'Identifier', + name: 'foo', + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + property: { + type: 'Identifier', + name: 'bar', + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + range: [4, 12], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 12 } + } + }, + 'arguments': [], + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + + 'new foo.bar()': { + type: 'ExpressionStatement', + expression: { + type: 'NewExpression', + callee: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'foo', + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + property: { + type: 'Identifier', + name: 'bar', + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + 'arguments': [], + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + '( new foo).bar()': { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'MemberExpression', + computed: false, + object: { + type: 'NewExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + 'arguments': [], + range: [2, 9], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 9 } + } + }, + property: { + type: 'Identifier', + name: 'bar', + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + 'arguments': [], + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + 'foo(bar, baz)': { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'bar', + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, { + type: 'Identifier', + name: 'baz', + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }], + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + '( foo )()': { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + 'arguments': [], + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'universe.milkyway': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'milkyway', + range: [9, 17], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + 'universe.milkyway.solarsystem': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'milkyway', + range: [9, 17], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + property: { + type: 'Identifier', + name: 'solarsystem', + range: [18, 29], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 29 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + + 'universe.milkyway.solarsystem.Earth': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'milkyway', + range: [9, 17], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + property: { + type: 'Identifier', + name: 'solarsystem', + range: [18, 29], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 29 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + property: { + type: 'Identifier', + name: 'Earth', + range: [30, 35], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + + 'universe[galaxyName, otherUselessName]': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: true, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'SequenceExpression', + expressions: [{ + type: 'Identifier', + name: 'galaxyName', + range: [9, 19], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 19 } + } + }, { + type: 'Identifier', + name: 'otherUselessName', + range: [21, 37], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 37 } + } + }], + range: [9, 37], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 37 } + } + }, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + + 'universe[galaxyName]': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: true, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'galaxyName', + range: [9, 19], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + + 'universe[42].galaxies': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: true, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Literal', + value: 42, + raw: '42', + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: 'Identifier', + name: 'galaxies', + range: [13, 21], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + + 'universe(42).galaxies': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + 'arguments': [{ + type: 'Literal', + value: 42, + raw: '42', + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }], + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: 'Identifier', + name: 'galaxies', + range: [13, 21], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + + 'universe(42).galaxies(14, 3, 77).milkyway': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'CallExpression', + callee: { + type: 'MemberExpression', + computed: false, + object: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + 'arguments': [{ + type: 'Literal', + value: 42, + raw: '42', + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }], + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: 'Identifier', + name: 'galaxies', + range: [13, 21], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + 'arguments': [{ + type: 'Literal', + value: 14, + raw: '14', + range: [22, 24], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 24 } + } + }, { + type: 'Literal', + value: 3, + raw: '3', + range: [26, 27], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, { + type: 'Literal', + value: 77, + raw: '77', + range: [29, 31], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 31 } + } + }], + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + property: { + type: 'Identifier', + name: 'milkyway', + range: [33, 41], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 41 } + } + }, + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + + 'earth.asia.Indonesia.prepareForElection(2014)': { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: false, + object: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'earth', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + property: { + type: 'Identifier', + name: 'asia', + range: [6, 10], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + property: { + type: 'Identifier', + name: 'Indonesia', + range: [11, 20], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + property: { + type: 'Identifier', + name: 'prepareForElection', + range: [21, 39], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 39 } + } + }, + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + 'arguments': [{ + type: 'Literal', + value: 2014, + raw: '2014', + range: [40, 44], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 44 } + } + }], + range: [0, 45], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 45 } + } + }, + range: [0, 45], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 45 } + } + }, + + 'universe.if': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'if', + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'universe.true': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'true', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'universe.false': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'false', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + 'universe.null': { + type: 'ExpressionStatement', + expression: { + type: 'MemberExpression', + computed: false, + object: { + type: 'Identifier', + name: 'universe', + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'Identifier', + name: 'null', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + + }, + + 'Postfix Expressions': { + + 'x++': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + prefix: false, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + 'x--': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + prefix: false, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + 'eval++': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'eval', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + prefix: false, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'eval--': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'eval', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + prefix: false, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'arguments++': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'arguments', + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + prefix: false, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'arguments--': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'arguments', + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + prefix: false, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + } + + }, + + 'Unary Operators': { + + '++x': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + prefix: true, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + '--x': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'x', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + prefix: true, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + '++eval': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'eval', + range: [2, 6], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 6 } + } + }, + prefix: true, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + '--eval': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'eval', + range: [2, 6], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 6 } + } + }, + prefix: true, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + '++arguments': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'arguments', + range: [2, 11], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 11 } + } + }, + prefix: true, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + '--arguments': { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'arguments', + range: [2, 11], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 11 } + } + }, + prefix: true, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + '+x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: '+', + argument: { + type: 'Identifier', + name: 'x', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + prefix: true, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + '-x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: '-', + argument: { + type: 'Identifier', + name: 'x', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + prefix: true, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + '~x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: '~', + argument: { + type: 'Identifier', + name: 'x', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + prefix: true, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + '!x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: '!', + argument: { + type: 'Identifier', + name: 'x', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + prefix: true, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + + 'void x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: 'void', + argument: { + type: 'Identifier', + name: 'x', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + prefix: true, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'delete x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: 'delete', + argument: { + type: 'Identifier', + name: 'x', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + prefix: true, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'typeof x': { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: 'typeof', + argument: { + type: 'Identifier', + name: 'x', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + prefix: true, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + } + + }, + + 'Multiplicative Operators': { + + 'x * y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x / y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '/', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x % y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '%', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + + }, + + 'Additive Operators': { + + 'x + y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x - y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + + }, + + 'Bitwise Shift Operator': { + + 'x << y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<<', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x >> y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '>>', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x >>> y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '>>>', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + + }, + + 'Relational Operators': { + + 'x < y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x > y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '>', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x <= y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x >= y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '>=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x in y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: 'in', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x instanceof y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: 'instanceof', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + 'x < y < z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + + }, + + 'Equality Operators': { + + 'x == y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '==', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x != y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '!=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x === y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '===', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x !== y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '!==', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + + }, + + 'Binary Bitwise Operators': { + + 'x & y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x ^ y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '^', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'x | y': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + + }, + + 'Binary Expressions': { + + 'x + y + z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x - y + z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x + y - z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x - y - z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x + y * z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x + y / z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '+', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '/', + left: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x - y % z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '-', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '%', + left: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x * y * z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x * y / z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '/', + left: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x * y % z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '%', + left: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x % y * z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'BinaryExpression', + operator: '%', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x << y << z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<<', + left: { + type: 'BinaryExpression', + operator: '<<', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'x | y | z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x & y & z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '&', + left: { + type: 'BinaryExpression', + operator: '&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x ^ y ^ z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '^', + left: { + type: 'BinaryExpression', + operator: '^', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x & y | z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'BinaryExpression', + operator: '&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x | y ^ z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '^', + left: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x | y & z': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '|', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '&', + left: { + type: 'Identifier', + name: 'y', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + + }, + + 'Binary Logical Operators': { + + 'x || y': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '||', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x && y': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '&&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'x || y || z': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '||', + left: { + type: 'LogicalExpression', + operator: '||', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'x && y && z': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '&&', + left: { + type: 'LogicalExpression', + operator: '&&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'x || y && z': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '||', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'LogicalExpression', + operator: '&&', + left: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'x || y ^ z': { + type: 'ExpressionStatement', + expression: { + type: 'LogicalExpression', + operator: '||', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'BinaryExpression', + operator: '^', + left: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'Identifier', + name: 'z', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + } + + }, + + 'Conditional Operator': { + + 'y ? 1 : 2': { + type: 'ExpressionStatement', + expression: { + type: 'ConditionalExpression', + test: { + type: 'Identifier', + name: 'y', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + consequent: { + type: 'Literal', + value: 1, + raw: '1', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + alternate: { + type: 'Literal', + value: 2, + raw: '2', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x && y ? 1 : 2': { + type: 'ExpressionStatement', + expression: { + type: 'ConditionalExpression', + test: { + type: 'LogicalExpression', + operator: '&&', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + consequent: { + type: 'Literal', + value: 1, + raw: '1', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + alternate: { + type: 'Literal', + value: 2, + raw: '2', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + + }, + + 'Assignment Operators': { + + 'x = 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'eval = 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'eval', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [7, 9], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'arguments = 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'arguments', + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + 'x *= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '*=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x /= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '/=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x %= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '%=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x += 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '+=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x -= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '-=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x <<= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '<<=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'x >>= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '>>=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [6, 8], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'x >>>= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '>>>=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [7, 9], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'x &= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '&=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x ^= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '^=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + 'x |= 42': { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '|=', + left: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [5, 7], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + + }, + + 'Block': { + + '{ foo }': { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'foo', + range: [2, 5], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 5 } + } + }, + range: [2, 6], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 6 } + } + }], + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '{ doThis(); doThat(); }': { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doThis', + range: [2, 8], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 8 } + } + }, + 'arguments': [], + range: [2, 10], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 10 } + } + }, + range: [2, 11], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 11 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doThat', + range: [12, 18], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 18 } + } + }, + 'arguments': [], + range: [12, 20], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 20 } + } + }, + range: [12, 21], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + + '{}': { + type: 'BlockStatement', + body: [], + range: [0, 2], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + } + + }, + + 'Variable Statement': { + + 'var x': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: null, + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }], + kind: 'var', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + 'var x, y;': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: null, + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + init: null, + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }], + kind: 'var', + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'var x = 42': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [8, 10], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 10 } + } + }, + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }], + kind: 'var', + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + + 'var eval = 42, arguments = 42': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'eval', + range: [4, 8], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 8 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [11, 13], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'arguments', + range: [15, 24], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 24 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [27, 29], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 29 } + } + }, + range: [15, 29], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 29 } + } + }], + kind: 'var', + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + + 'var x = 14, y = 3, z = 1977': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: 'Literal', + value: 14, + raw: '14', + range: [8, 10], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 10 } + } + }, + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + init: { + type: 'Literal', + value: 3, + raw: '3', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + range: [12, 17], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 17 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'z', + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + init: { + type: 'Literal', + value: 1977, + raw: '1977', + range: [23, 27], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 27 } + } + }, + range: [19, 27], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 27 } + } + }], + kind: 'var', + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + + 'var implements, interface, package': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'implements', + range: [4, 14], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 14 } + } + }, + init: null, + range: [4, 14], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 14 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'interface', + range: [16, 25], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 25 } + } + }, + init: null, + range: [16, 25], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 25 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'package', + range: [27, 34], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 34 } + } + }, + init: null, + range: [27, 34], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 34 } + } + }], + kind: 'var', + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + + 'var private, protected, public, static': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'private', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + init: null, + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'protected', + range: [13, 22], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 22 } + } + }, + init: null, + range: [13, 22], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 22 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'public', + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + init: null, + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'static', + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }, + init: null, + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }], + kind: 'var', + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + } + + }, + + 'Let Statement': { + + 'let x': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: null, + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }], + kind: 'let', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + + '{ let x }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + init: null, + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }], + kind: 'let', + range: [2, 8], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 8 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + '{ let x = 42 }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }], + kind: 'let', + range: [2, 13], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 13 } + } + }], + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + + '{ let x = 14, y = 3, z = 1977 }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + init: { + type: 'Literal', + value: 14, + raw: '14', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + init: { + type: 'Literal', + value: 3, + raw: '3', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + range: [14, 19], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 19 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'z', + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + init: { + type: 'Literal', + value: 1977, + raw: '1977', + range: [25, 29], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 29 } + } + }, + range: [21, 29], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 29 } + } + }], + kind: 'let', + range: [2, 30], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 30 } + } + }], + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + } + + }, + + 'Const Statement': { + + 'const x = 42': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }], + kind: 'const', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + + '{ const x = 42 }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }], + kind: 'const', + range: [2, 15], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 15 } + } + }], + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + + '{ const x = 14, y = 3, z = 1977 }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'Literal', + value: 14, + raw: '14', + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + init: { + type: 'Literal', + value: 3, + raw: '3', + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + range: [16, 21], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 21 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'z', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + init: { + type: 'Literal', + value: 1977, + raw: '1977', + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + range: [23, 31], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 31 } + } + }], + kind: 'const', + range: [2, 32], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 32 } + } + }], + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + } + + }, + + 'Empty Statement': { + + ';': { + type: 'EmptyStatement', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + } + + }, + + 'Expression Statement': { + + 'x': { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + + 'x, y': { + type: 'ExpressionStatement', + expression: { + type: 'SequenceExpression', + expressions: [{ + type: 'Identifier', + name: 'x', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, { + type: 'Identifier', + name: 'y', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }], + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + + '\\u0061': { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'a', + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }, + + 'a\\u0061': { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'aa', + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + + '\\ua': { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'ua', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + + 'a\\u': { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'au', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + } + + }, + + 'If Statement': { + + 'if (morning) goodMorning()': { + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'morning', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + consequent: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'goodMorning', + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }, + 'arguments': [], + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + alternate: null, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + + 'if (morning) (function(){})': { + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'morning', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + consequent: { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [24, 26], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 26 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 26], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 26 } + } + }, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }, + alternate: null, + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + + 'if (morning) var x = 0;': { + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'morning', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + consequent: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + init: { + type: 'Literal', + value: 0, + raw: '0', + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + range: [17, 22], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 22 } + } + }], + kind: 'var', + range: [13, 23], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 23 } + } + }, + alternate: null, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + + 'if (morning) function a(){}': { + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'morning', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + consequent: { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'a', + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [25, 27], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 27 } + } + }, + rest: null, + generator: false, + expression: false, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }, + alternate: null, + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + + 'if (morning) goodMorning(); else goodDay()': { + type: 'IfStatement', + test: { + type: 'Identifier', + name: 'morning', + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + consequent: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'goodMorning', + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }, + 'arguments': [], + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }, + alternate: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'goodDay', + range: [33, 40], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 40 } + } + }, + 'arguments': [], + range: [33, 42], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 42 } + } + }, + range: [33, 42], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 42 } + } + }, + range: [0, 42], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 42 } + } + } + + }, + + 'Iteration Statements': { + + 'do keep(); while (true)': { + type: 'DoWhileStatement', + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'keep', + range: [3, 7], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 7 } + } + }, + 'arguments': [], + range: [3, 9], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 9 } + } + }, + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } + } + }, + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + + 'do keep(); while (true);': { + type: 'DoWhileStatement', + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'keep', + range: [3, 7], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 7 } + } + }, + 'arguments': [], + range: [3, 9], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 9 } + } + }, + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } + } + }, + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'do { x++; y--; } while (x < 10)': { + type: 'DoWhileStatement', + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + prefix: false, + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 9 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'y', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + prefix: false, + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }], + range: [3, 16], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 16 } + } + }, + test: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + right: { + type: 'Literal', + value: 10, + raw: '10', + range: [28, 30], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 30 } + } + }, + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + + '{ do { } while (false) false }': { + type: 'BlockStatement', + body: [{ + type: 'DoWhileStatement', + body: { + type: 'BlockStatement', + body: [], + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + test: { + type: 'Literal', + value: false, + raw: 'false', + range: [16, 21], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 21 } + } + }, + range: [2, 22], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 22 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: false, + raw: 'false', + range: [23, 28], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 28 } + } + }, + range: [23, 29], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 29 } + } + }], + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + + 'while (true) doSomething()': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doSomething', + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }, + 'arguments': [], + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + + 'while (x < 10) { x++; y--; }': { + type: 'WhileStatement', + test: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + right: { + type: 'Literal', + value: 10, + raw: '10', + range: [11, 13], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + range: [7, 13], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 13 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + prefix: false, + range: [17, 20], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 20 } + } + }, + range: [17, 21], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 21 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'y', + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + prefix: false, + range: [22, 25], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 25 } + } + }, + range: [22, 26], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 26 } + } + }], + range: [15, 28], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 28 } + } + }, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + + 'for(;;);': { + type: 'ForStatement', + init: null, + test: null, + update: null, + body: { + type: 'EmptyStatement', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'for(;;){}': { + type: 'ForStatement', + init: null, + test: null, + update: null, + body: { + type: 'BlockStatement', + body: [], + range: [7, 9], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + 'for(x = 0;;);': { + type: 'ForStatement', + init: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + test: null, + update: null, + body: { + type: 'EmptyStatement', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'for(var x = 0;;);': { + type: 'ForStatement', + init: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'Literal', + value: 0, + raw: '0', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }], + kind: 'var', + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, + test: null, + update: null, + body: { + type: 'EmptyStatement', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + 'for(let x = 0;;);': { + type: 'ForStatement', + init: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'Literal', + value: 0, + raw: '0', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }], + kind: 'let', + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, + test: null, + update: null, + body: { + type: 'EmptyStatement', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + + 'for(var x = 0, y = 1;;);': { + type: 'ForStatement', + init: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'Literal', + value: 0, + raw: '0', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + init: { + type: 'Literal', + value: 1, + raw: '1', + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + range: [15, 20], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }], + kind: 'var', + range: [4, 20], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 20 } + } + }, + test: null, + update: null, + body: { + type: 'EmptyStatement', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'for(x = 0; x < 42;);': { + type: 'ForStatement', + init: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + test: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + update: null, + body: { + type: 'EmptyStatement', + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + + 'for(x = 0; x < 42; x++);': { + type: 'ForStatement', + init: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + test: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + update: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + prefix: false, + range: [19, 22], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 22 } + } + }, + body: { + type: 'EmptyStatement', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'for(x = 0; x < 42; x++) process(x);': { + type: 'ForStatement', + init: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + test: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'Identifier', + name: 'x', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + right: { + type: 'Literal', + value: 42, + raw: '42', + range: [15, 17], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 17 } + } + }, + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + update: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'x', + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + prefix: false, + range: [19, 22], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 22 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [24, 31], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 31 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [32, 33], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 33 } + } + }], + range: [24, 34], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 34 } + } + }, + range: [24, 35], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + + 'for(x in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [15, 22], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 22 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }], + range: [15, 25], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 25 } + } + }, + range: [15, 26], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 26 } + } + }, + each: false, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + + 'for (var x in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: null, + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }], + kind: 'var', + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [28, 29], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }], + range: [20, 30], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + each: false, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + + 'for (var x = 42 in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [13, 15], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 15 } + } + }, + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }], + kind: 'var', + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [19, 23], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 23 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [25, 32], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 32 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [33, 34], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 34 } + } + }], + range: [25, 35], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 35 } + } + }, + range: [25, 36], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 36 } + } + }, + each: false, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'for (let x in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: null, + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }], + kind: 'let', + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [28, 29], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }], + range: [20, 30], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 30 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + each: false, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + + 'for (let x = 42 in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: { + type: 'Literal', + value: 42, + raw: '42', + range: [13, 15], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 15 } + } + }, + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }], + kind: 'let', + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [19, 23], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 23 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [25, 32], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 32 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [33, 34], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 34 } + } + }], + range: [25, 35], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 35 } + } + }, + range: [25, 36], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 36 } + } + }, + each: false, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'for (var i = function() { return 10 in [] } in list) process(x);': { + type: 'ForInStatement', + left: { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'i', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ReturnStatement', + argument: { + type: 'BinaryExpression', + operator: 'in', + left: { + type: 'Literal', + value: 10, + raw: '10', + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [39, 41], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 41 } + } + }, + range: [33, 41], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 41 } + } + }, + range: [26, 42], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 42 } + } + }], + range: [24, 43], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 43 } + } + }, + rest: null, + generator: false, + expression: false, + range: [13, 43], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 43 } + } + }, + range: [9, 43], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 43 } + } + }], + kind: 'var', + range: [5, 43], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 43 } + } + }, + right: { + type: 'Identifier', + name: 'list', + range: [47, 51], + loc: { + start: { line: 1, column: 47 }, + end: { line: 1, column: 51 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'process', + range: [53, 60], + loc: { + start: { line: 1, column: 53 }, + end: { line: 1, column: 60 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'x', + range: [61, 62], + loc: { + start: { line: 1, column: 61 }, + end: { line: 1, column: 62 } + } + }], + range: [53, 63], + loc: { + start: { line: 1, column: 53 }, + end: { line: 1, column: 63 } + } + }, + range: [53, 64], + loc: { + start: { line: 1, column: 53 }, + end: { line: 1, column: 64 } + } + }, + each: false, + range: [0, 64], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 64 } + } + } + + }, + + 'continue statement': { + + 'while (true) { continue; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'ContinueStatement', + label: null, + range: [15, 24], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 24 } + } + } + ], + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + + 'while (true) { continue }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'ContinueStatement', + label: null, + range: [15, 24], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 24 } + } + } + ], + range: [13, 25], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 25 } + } + }, + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + + 'done: while (true) { continue done }': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'done', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + body: { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [13, 17], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'ContinueStatement', + label: { + type: 'Identifier', + name: 'done', + range: [30, 34], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 34 } + } + }, + range: [21, 35], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 35 } + } + } + ], + range: [19, 36], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 36 } + } + }, + range: [6, 36], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + + 'done: while (true) { continue done; }': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'done', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + body: { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [13, 17], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'ContinueStatement', + label: { + type: 'Identifier', + name: 'done', + range: [30, 34], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 34 } + } + }, + range: [21, 35], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 35 } + } + } + ], + range: [19, 37], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 37 } + } + }, + range: [6, 37], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 37 } + } + }, + range: [0, 37], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 37 } + } + } + + }, + + 'break statement': { + + 'while (true) { break }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'BreakStatement', + label: null, + range: [15, 21], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 21 } + } + } + ], + range: [13, 22], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + + 'done: while (true) { break done }': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'done', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + body: { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [13, 17], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'BreakStatement', + label: { + type: 'Identifier', + name: 'done', + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + range: [21, 32], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 32 } + } + } + ], + range: [19, 33], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 33 } + } + }, + range: [6, 33], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 33 } + } + }, + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + }, + + 'done: while (true) { break done; }': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'done', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + body: { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [13, 17], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + body: { + type: 'BlockStatement', + body: [ + { + type: 'BreakStatement', + label: { + type: 'Identifier', + name: 'done', + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + range: [21, 32], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 32 } + } + } + ], + range: [19, 34], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 34 } + } + }, + range: [6, 34], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + } + + }, + + 'return statement': { + + '(function(){ return })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: null, + range: [13, 20], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 20 } + } + } + ], + range: [11, 21], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 21 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 21], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + + '(function(){ return; })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: null, + range: [13, 20], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 20 } + } + } + ], + range: [11, 22], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 22 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 22], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + + '(function(){ return x; })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: { + type: 'Identifier', + name: 'x', + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + range: [13, 22], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 22 } + } + } + ], + range: [11, 24], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 24 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 24], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + + '(function(){ return x * y })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + range: [20, 25], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 25 } + } + }, + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + } + ], + range: [11, 27], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 27 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 27], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 27 } + } + }, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + } + }, + + 'with statement': { + + 'with (x) foo = bar': { + type: 'WithStatement', + object: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'foo', + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + right: { + type: 'Identifier', + name: 'bar', + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + range: [9, 18], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 18 } + } + }, + range: [9, 18], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + + 'with (x) foo = bar;': { + type: 'WithStatement', + object: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + body: { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'foo', + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + right: { + type: 'Identifier', + name: 'bar', + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + range: [9, 18], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 18 } + } + }, + range: [9, 19], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + + 'with (x) { foo = bar }': { + type: 'WithStatement', + object: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'foo', + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + right: { + type: 'Identifier', + name: 'bar', + range: [17, 20], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 20 } + } + }, + range: [11, 20], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 20 } + } + }, + range: [11, 21], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 21 } + } + }], + range: [9, 22], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + } + + }, + + 'switch statement': { + + 'switch (x) {}': { + type: 'SwitchStatement', + discriminant: { + type: 'Identifier', + name: 'x', + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + cases:[], + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + + 'switch (answer) { case 42: hi(); break; }': { + type: 'SwitchStatement', + discriminant: { + type: 'Identifier', + name: 'answer', + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + cases: [{ + type: 'SwitchCase', + test: { + type: 'Literal', + value: 42, + raw: '42', + range: [23, 25], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 25 } + } + }, + consequent: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'hi', + range: [27, 29], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 29 } + } + }, + 'arguments': [], + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, { + type: 'BreakStatement', + label: null, + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }], + range: [18, 39], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 39 } + } + }], + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + + 'switch (answer) { case 42: hi(); break; default: break }': { + type: 'SwitchStatement', + discriminant: { + type: 'Identifier', + name: 'answer', + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + cases: [{ + type: 'SwitchCase', + test: { + type: 'Literal', + value: 42, + raw: '42', + range: [23, 25], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 25 } + } + }, + consequent: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'hi', + range: [27, 29], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 29 } + } + }, + 'arguments': [], + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, { + type: 'BreakStatement', + label: null, + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }], + range: [18, 39], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 39 } + } + }, { + type: 'SwitchCase', + test: null, + consequent: [{ + type: 'BreakStatement', + label: null, + range: [49, 55], + loc: { + start: { line: 1, column: 49 }, + end: { line: 1, column: 55 } + } + }], + range: [40, 55], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 55 } + } + }], + range: [0, 56], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 56 } + } + } + + }, + + 'Labelled Statements': { + + 'start: for (;;) break start': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'start', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + body: { + type: 'ForStatement', + init: null, + test: null, + update: null, + body: { + type: 'BreakStatement', + label: { + type: 'Identifier', + name: 'start', + range: [22, 27], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + }, + range: [16, 27], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 27 } + } + }, + range: [7, 27], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 27 } + } + }, + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + + 'start: while (true) break start': { + type: 'LabeledStatement', + label: { + type: 'Identifier', + name: 'start', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + body: { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + body: { + type: 'BreakStatement', + label: { + type: 'Identifier', + name: 'start', + range: [26, 31], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 31 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + range: [7, 31], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 31 } + } + }, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + } + + }, + + 'throw statement': { + + 'throw x;': { + type: 'ThrowStatement', + argument: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [0, 8], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + }, + + 'throw x * y': { + type: 'ThrowStatement', + argument: { + type: 'BinaryExpression', + operator: '*', + left: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + right: { + type: 'Identifier', + name: 'y', + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [6, 11], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + 'throw { message: "Error" }': { + type: 'ThrowStatement', + argument: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'message', + range: [8, 15], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: 'Literal', + value: 'Error', + raw: '"Error"', + range: [17, 24], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 24 } + } + }, + kind: 'init', + range: [8, 24], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 24 } + } + }], + range: [6, 26], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 26 } + } + }, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + } + + }, + + 'try statement': { + + 'try { } catch (e) { }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'e', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [18, 21], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 21 } + } + }, + range: [8, 21], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 21 } + } + }], + finalizer: null, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + + 'try { } catch (eval) { }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'eval', + range: [15, 19], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 19 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + range: [8, 24], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 24 } + } + }], + finalizer: null, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'try { } catch (arguments) { }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'arguments', + range: [15, 24], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 24 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [26, 29], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 29 } + } + }, + range: [8, 29], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 29 } + } + }], + finalizer: null, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + + 'try { } catch (e) { say(e) }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'e', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'say', + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'e', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }], + range: [20, 26], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 26 } + } + }, + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }], + range: [18, 28], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 28 } + } + }, + range: [8, 28], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 28 } + } + }], + finalizer: null, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + + 'try { } finally { cleanup(stuff) }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [4, 7], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + guardedHandlers: [], + handlers: [], + finalizer: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'cleanup', + range: [18, 25], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 25 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'stuff', + range: [26, 31], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 31 } + } + }], + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + range: [18, 33], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 33 } + } + }], + range: [16, 34], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + + 'try { doThat(); } catch (e) { say(e) }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doThat', + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }, + 'arguments': [], + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }, + range: [6, 15], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 15 } + } + }], + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'e', + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'say', + range: [30, 33], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 33 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'e', + range: [34, 35], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }], + range: [30, 36], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 36 } + } + }, + range: [30, 37], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 37 } + } + }], + range: [28, 38], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 38 } + } + }, + range: [18, 38], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 38 } + } + }], + finalizer: null, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + + 'try { doThat(); } catch (e) { say(e) } finally { cleanup(stuff) }': { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'doThat', + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }, + 'arguments': [], + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }, + range: [6, 15], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 15 } + } + }], + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'e', + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'say', + range: [30, 33], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 33 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'e', + range: [34, 35], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }], + range: [30, 36], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 36 } + } + }, + range: [30, 37], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 37 } + } + }], + range: [28, 38], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 38 } + } + }, + range: [18, 38], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 38 } + } + }], + finalizer: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'cleanup', + range: [49, 56], + loc: { + start: { line: 1, column: 49 }, + end: { line: 1, column: 56 } + } + }, + 'arguments': [{ + type: 'Identifier', + name: 'stuff', + range: [57, 62], + loc: { + start: { line: 1, column: 57 }, + end: { line: 1, column: 62 } + } + }], + range: [49, 63], + loc: { + start: { line: 1, column: 49 }, + end: { line: 1, column: 63 } + } + }, + range: [49, 64], + loc: { + start: { line: 1, column: 49 }, + end: { line: 1, column: 64 } + } + }], + range: [47, 65], + loc: { + start: { line: 1, column: 47 }, + end: { line: 1, column: 65 } + } + }, + range: [0, 65], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 65 } + } + } + + }, + + 'debugger statement': { + + 'debugger;': { + type: 'DebuggerStatement', + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + + }, + + 'Function Definition': { + + 'function hello() { sayHi(); }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'hello', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'sayHi', + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + 'arguments': [], + range: [19, 26], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 26 } + } + }, + range: [19, 27], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 27 } + } + }], + range: [17, 29], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 29 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + + 'function eval() { }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'eval', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [16, 19], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 19 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + + 'function arguments() { }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'arguments', + range: [9, 18], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 18 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + 'function test(t, t) { }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'test', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + params: [{ + type: 'Identifier', + name: 't', + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, { + type: 'Identifier', + name: 't', + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + + '(function test(t, t) { })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'test', + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + params: [{ + type: 'Identifier', + name: 't', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, { + type: 'Identifier', + name: 't', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 24], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + + 'function eval() { function inner() { "use strict" } }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'eval', + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'inner', + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '\"use strict\"', + range: [37, 49], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 49 } + } + }, + range: [37, 50], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 50 } + } + }], + range: [35, 51], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 51 } + } + }, + rest: null, + generator: false, + expression: false, + range: [18, 51], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 51 } + } + }], + range: [16, 53], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 53 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 53], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 53 } + } + }, + + 'function hello(a) { sayHi(); }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'hello', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + params: [{ + type: 'Identifier', + name: 'a', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'sayHi', + range: [20, 25], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 25 } + } + }, + 'arguments': [], + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }, + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }], + range: [18, 30], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 30 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + + 'function hello(a, b) { sayHi(); }': { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'hello', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + params: [{ + type: 'Identifier', + name: 'a', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, { + type: 'Identifier', + name: 'b', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'sayHi', + range: [23, 28], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 28 } + } + }, + 'arguments': [], + range: [23, 30], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 30 } + } + }, + range: [23, 31], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 31 } + } + }], + range: [21, 33], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + }, + + 'var hi = function() { sayHi() };': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'hi', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + init: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'sayHi', + range: [22, 27], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + }, + 'arguments': [], + range: [22, 29], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 29 } + } + }, + range: [22, 30], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 30 } + } + }], + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + rest: null, + generator: false, + expression: false, + range: [9, 31], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 31 } + } + }, + range: [4, 31], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 31 } + } + }], + kind: 'var', + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + + 'var hi = function eval() { };': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'hi', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + init: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'eval', + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [25, 28], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 28 } + } + }, + rest: null, + generator: false, + expression: false, + range: [9, 28], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 28 } + } + }, + range: [4, 28], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 28 } + } + }], + kind: 'var', + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + + 'var hi = function arguments() { };': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'hi', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + init: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'arguments', + range: [18, 27], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 27 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [30, 33], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + generator: false, + expression: false, + range: [9, 33], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 33 } + } + }, + range: [4, 33], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 33 } + } + }], + kind: 'var', + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + + 'var hello = function hi() { sayHi() };': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'hello', + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'hi', + range: [21, 23], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 23 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'sayHi', + range: [28, 33], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 33 } + } + }, + 'arguments': [], + range: [28, 35], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 35 } + } + }, + range: [28, 36], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 36 } + } + }], + range: [26, 37], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 37 } + } + }, + rest: null, + generator: false, + expression: false, + range: [12, 37], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 37 } + } + }, + range: [4, 37], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 37 } + } + }], + kind: 'var', + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + + '(function(){})': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [11, 13], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 13], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + + }, + + 'Automatic semicolon insertion': { + + '{ x\n++y }': { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + range: [2, 4], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 0 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'y', + range: [6, 7], + loc: { + start: { line: 2, column: 2 }, + end: { line: 2, column: 3 } + } + }, + prefix: true, + range: [4, 7], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 3 } + } + }, + range: [4, 8], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 4 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, + + '{ x\n--y }': { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + range: [2, 4], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 0 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'y', + range: [6, 7], + loc: { + start: { line: 2, column: 2 }, + end: { line: 2, column: 3 } + } + }, + prefix: true, + range: [4, 7], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 3 } + } + }, + range: [4, 8], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 4 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, + + 'var x /* comment */;': { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: null, + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }], + kind: 'var', + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + + '{ var x = 14, y = 3\nz; }': { + type: 'BlockStatement', + body: [{ + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + init: { + type: 'Literal', + value: 14, + raw: '14', + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + range: [6, 12], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 12 } + } + }, { + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'y', + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + init: { + type: 'Literal', + value: 3, + raw: '3', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + range: [14, 19], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 19 } + } + }], + kind: 'var', + range: [2, 20], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 0 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'z', + range: [20, 21], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 1 } + } + }, + range: [20, 22], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + }], + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 4 } + } + }, + + 'while (true) { continue\nthere; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ContinueStatement', + label: null, + range: [15, 23], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 23 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [24, 29], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [24, 30], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [13, 32], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 8 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + 'while (true) { continue // Comment\nthere; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ContinueStatement', + label: null, + range: [15, 23], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 23 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [35, 40], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [35, 41], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [13, 43], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 8 } + } + }, + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + 'while (true) { continue /* Multiline\nComment */there; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'ContinueStatement', + label: null, + range: [15, 23], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 23 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [47, 52], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 15 } + } + }, + range: [47, 53], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 16 } + } + }], + range: [13, 55], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 18 } + } + }, + range: [0, 55], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 18 } + } + }, + + 'while (true) { break\nthere; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'BreakStatement', + label: null, + range: [15, 20], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [21, 26], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [21, 27], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [13, 29], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 8 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + 'while (true) { break // Comment\nthere; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'BreakStatement', + label: null, + range: [15, 20], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [32, 37], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [32, 38], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [13, 40], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 8 } + } + }, + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + 'while (true) { break /* Multiline\nComment */there; }': { + type: 'WhileStatement', + test: { + type: 'Literal', + value: true, + raw: 'true', + range: [7, 11], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 11 } + } + }, + body: { + type: 'BlockStatement', + body: [{ + type: 'BreakStatement', + label: null, + range: [15, 20], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'there', + range: [44, 49], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 15 } + } + }, + range: [44, 50], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 16 } + } + }], + range: [13, 52], + loc: { + start: { line: 1, column: 13 }, + end: { line: 2, column: 18 } + } + }, + range: [0, 52], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 18 } + } + }, + + '(function(){ return\nx; })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: null, + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [20, 21], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 1 } + } + }, + range: [20, 22], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + } + ], + range: [11, 24], + loc: { + start: { line: 1, column: 11 }, + end: { line: 2, column: 4 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 24], + loc: { + start: { line: 1, column: 1 }, + end: { line: 2, column: 4 } + } + }, + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, + + '(function(){ return // Comment\nx; })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: null, + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [31, 32], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 1 } + } + }, + range: [31, 33], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 2 } + } + } + ], + range: [11, 35], + loc: { + start: { line: 1, column: 11 }, + end: { line: 2, column: 4 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 35], + loc: { + start: { line: 1, column: 1 }, + end: { line: 2, column: 4 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, + + '(function(){ return/* Multiline\nComment */x; })': { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: null, + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'x', + range: [42, 43], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 11 } + } + }, + range: [42, 44], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 12 } + } + } + ], + range: [11, 46], + loc: { + start: { line: 1, column: 11 }, + end: { line: 2, column: 14 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 46], + loc: { + start: { line: 1, column: 1 }, + end: { line: 2, column: 14 } + } + }, + range: [0, 47], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 15 } + } + }, + + '{ throw error\nerror; }': { + type: 'BlockStatement', + body: [{ + type: 'ThrowStatement', + argument: { + type: 'Identifier', + name: 'error', + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, + range: [2, 14], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 0 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'error', + range: [14, 19], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [14, 20], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + '{ throw error// Comment\nerror; }': { + type: 'BlockStatement', + body: [{ + type: 'ThrowStatement', + argument: { + type: 'Identifier', + name: 'error', + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, + range: [2, 24], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 0 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'error', + range: [24, 29], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [24, 30], + loc: { + start: { line: 2, column: 0 }, + end: { line: 2, column: 6 } + } + }], + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 8 } + } + }, + + '{ throw error/* Multiline\nComment */error; }': { + type: 'BlockStatement', + body: [{ + type: 'ThrowStatement', + argument: { + type: 'Identifier', + name: 'error', + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, + range: [2, 36], + loc: { + start: { line: 1, column: 2 }, + end: { line: 2, column: 10 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'error', + range: [36, 41], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 15 } + } + }, + range: [36, 42], + loc: { + start: { line: 2, column: 10 }, + end: { line: 2, column: 16 } + } + }], + range: [0, 44], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 18 } + } + } + + }, + + 'Source elements': { + + '': { + type: 'Program', + body: [], + range: [0, 0], + loc: { + start: { line: 0, column: 0 }, + end: { line: 0, column: 0 } + }, + tokens: [] + } + }, + + 'Invalid syntax': { + + '{': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected end of input' + }, + + '}': { + index: 0, + lineNumber: 1, + column: 1, + message: 'Error: Line 1: Unexpected token }' + }, + + '3ea': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3in []': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3e': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3e+': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3e-': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3x': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3x0': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '0x': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '09': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '018': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '01a': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '3in[]': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '0x3in[]': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '"Hello\nWorld"': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'x\\': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'x\\u005c': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'x\\u002a': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'var x = /(s/g': { + index: 13, + lineNumber: 1, + column: 14, + message: 'Error: Line 1: Invalid regular expression' + }, + + '/': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid regular expression: missing /' + }, + + '/test': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Invalid regular expression: missing /' + }, + + 'var x = /[a-z]/\\ux': { + index: 18, + lineNumber: 1, + column: 19, + message: 'Error: Line 1: Invalid regular expression' + }, + + '3 = 4': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + 'func() = 4': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '(1 + 1) = 10': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '1++': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '1--': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '++1': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '--1': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + 'for((1 + 1) in list) process(x);': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Invalid left-hand side in for-in' + }, + + '[': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected end of input' + }, + + '[,': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected end of input' + }, + + '1 + {': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Unexpected end of input' + }, + + '1 + { t:t ': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Unexpected end of input' + }, + + '1 + { t:t,': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'var x = /\n/': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Invalid regular expression: missing /' + }, + + 'var x = "\n': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'var if = 42': { + index: 4, + lineNumber: 1, + column: 5, + message: 'Error: Line 1: Unexpected token if' + }, + + 'i + 2 = 42': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '+i = 42': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }, + + '1 + (': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Unexpected end of input' + }, + + '\n\n\n{': { + index: 4, + lineNumber: 4, + column: 2, + message: 'Error: Line 4: Unexpected end of input' + }, + + '\n/* Some multiline\ncomment */\n)': { + index: 30, + lineNumber: 4, + column: 1, + message: 'Error: Line 4: Unexpected token )' + }, + + '{ set 1 }': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Unexpected number' + }, + + '{ get 2 }': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Unexpected number' + }, + + '({ set: s(if) { } })': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Unexpected token if' + }, + + '({ set s(.) { } })': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token .' + }, + + '({ set s() { } })': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token )' + }, + + '({ set: s() { } })': { + index: 12, + lineNumber: 1, + column: 13, + message: 'Error: Line 1: Unexpected token {' + }, + + '({ set: s(a, b) { } })': { + index: 16, + lineNumber: 1, + column: 17, + message: 'Error: Line 1: Unexpected token {' + }, + + '({ get: g(d) { } })': { + index: 13, + lineNumber: 1, + column: 14, + message: 'Error: Line 1: Unexpected token {' + }, + + '({ get i() { }, i: 42 })': { + index: 21, + lineNumber: 1, + column: 22, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }, + + '({ i: 42, get i() { } })': { + index: 21, + lineNumber: 1, + column: 22, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }, + + '({ set i(x) { }, i: 42 })': { + index: 22, + lineNumber: 1, + column: 23, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }, + + '({ i: 42, set i(x) { } })': { + index: 22, + lineNumber: 1, + column: 23, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }, + + '({ get i() { }, get i() { } })': { + index: 27, + lineNumber: 1, + column: 28, + message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name' + }, + + '({ set i(x) { }, set i(x) { } })': { + index: 29, + lineNumber: 1, + column: 30, + message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name' + }, + + 'function t(if) { }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Unexpected token if' + }, + + 'function t(true) { }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Unexpected token true' + }, + + 'function t(false) { }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Unexpected token false' + }, + + 'function t(null) { }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Unexpected token null' + }, + + 'function null() { }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token null' + }, + + 'function true() { }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token true' + }, + + 'function false() { }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token false' + }, + + 'function if() { }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token if' + }, + + 'a b;': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected identifier' + }, + + 'if.a;': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token .' + }, + + 'a if;': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token if' + }, + + 'a class;': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected reserved word' + }, + + 'break\n': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Illegal break statement' + }, + + 'break 1;': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Unexpected number' + }, + + 'continue\n': { + index: 8, + lineNumber: 1, + column: 9, + message: 'Error: Line 1: Illegal continue statement' + }, + + 'continue 2;': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected number' + }, + + 'throw': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'throw;': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Unexpected token ;' + }, + + 'throw\n': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Illegal newline after throw' + }, + + 'for (var i, i2 in {});': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Unexpected token in' + }, + + 'for ((i in {}));': { + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Unexpected token )' + }, + + 'for (i + 1 in {});': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Invalid left-hand side in for-in' + }, + + 'for (+i in {});': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Invalid left-hand side in for-in' + }, + + 'if(false)': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'if(false) doThis(); else': { + index: 24, + lineNumber: 1, + column: 25, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'do': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'while(false)': { + index: 12, + lineNumber: 1, + column: 13, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'for(;;)': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'with(x)': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'try { }': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Missing catch or finally after try' + }, + + 'try {} catch (42) {} ': { + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Unexpected number' + }, + + 'try {} catch (answer()) {} ': { + index: 20, + lineNumber: 1, + column: 21, + message: 'Error: Line 1: Unexpected token (' + }, + + 'try {} catch (-x) {} ': { + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Unexpected token -' + }, + + + '\u203F = 10': { + index: 0, + lineNumber: 1, + column: 1, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'const x = 12, y;': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Unexpected token ;' + }, + + 'const x, y = 12;': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ,' + }, + + 'const x;': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ;' + }, + + 'if(true) let a = 1;': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token let' + }, + + 'if(true) const a = 1;': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token const' + }, + + 'switch (c) { default: default: }': { + index: 30, + lineNumber: 1, + column: 31, + message: 'Error: Line 1: More than one default clause in switch statement' + }, + + 'new X()."s"': { + index: 8, + lineNumber: 1, + column: 9, + message: 'Error: Line 1: Unexpected string' + }, + + '/*': { + index: 2, + lineNumber: 1, + column: 3, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '/*\n\n\n': { + index: 5, + lineNumber: 4, + column: 1, + message: 'Error: Line 4: Unexpected token ILLEGAL' + }, + + '/**': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '/*\n\n*': { + index: 5, + lineNumber: 3, + column: 2, + message: 'Error: Line 3: Unexpected token ILLEGAL' + }, + + '/*hello': { + index: 7, + lineNumber: 1, + column: 8, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '/*hello *': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '\n]': { + index: 1, + lineNumber: 2, + column: 1, + message: 'Error: Line 2: Unexpected token ]' + }, + + '\r]': { + index: 1, + lineNumber: 2, + column: 1, + message: 'Error: Line 2: Unexpected token ]' + }, + + '\r\n]': { + index: 2, + lineNumber: 2, + column: 1, + message: 'Error: Line 2: Unexpected token ]' + }, + + '\n\r]': { + index: 2, + lineNumber: 3, + column: 1, + message: 'Error: Line 3: Unexpected token ]' + }, + + '//\r\n]': { + index: 4, + lineNumber: 2, + column: 1, + message: 'Error: Line 2: Unexpected token ]' + }, + + '//\n\r]': { + index: 4, + lineNumber: 3, + column: 1, + message: 'Error: Line 3: Unexpected token ]' + }, + + '/a\\\n/': { + index: 4, + lineNumber: 1, + column: 5, + message: 'Error: Line 1: Invalid regular expression: missing /' + }, + + '//\r \n]': { + index: 5, + lineNumber: 3, + column: 1, + message: 'Error: Line 3: Unexpected token ]' + }, + + '/*\r\n*/]': { + index: 6, + lineNumber: 2, + column: 3, + message: 'Error: Line 2: Unexpected token ]' + }, + + '/*\n\r*/]': { + index: 6, + lineNumber: 3, + column: 3, + message: 'Error: Line 3: Unexpected token ]' + }, + + '/*\r \n*/]': { + index: 7, + lineNumber: 3, + column: 3, + message: 'Error: Line 3: Unexpected token ]' + }, + + '\\\\': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '\\u005c': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + + '\\x': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '\\u0000': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '\u200C = []': { + index: 0, + lineNumber: 1, + column: 1, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '\u200D = []': { + index: 0, + lineNumber: 1, + column: 1, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '"\\': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + '"\\u': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected token ILLEGAL' + }, + + 'try { } catch() {}': { + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Unexpected token )' + }, + + 'return': { + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Illegal return statement' + }, + + 'break': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Illegal break statement' + }, + + 'continue': { + index: 8, + lineNumber: 1, + column: 9, + message: 'Error: Line 1: Illegal continue statement' + }, + + 'switch (x) { default: continue; }': { + index: 31, + lineNumber: 1, + column: 32, + message: 'Error: Line 1: Illegal continue statement' + }, + + 'do { x } *': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token *' + }, + + 'while (true) { break x; }': { + index: 22, + lineNumber: 1, + column: 23, + message: 'Error: Line 1: Undefined label \'x\'' + }, + + 'while (true) { continue x; }': { + index: 25, + lineNumber: 1, + column: 26, + message: 'Error: Line 1: Undefined label \'x\'' + }, + + 'x: while (true) { (function () { break x; }); }': { + index: 40, + lineNumber: 1, + column: 41, + message: 'Error: Line 1: Undefined label \'x\'' + }, + + 'x: while (true) { (function () { continue x; }); }': { + index: 43, + lineNumber: 1, + column: 44, + message: 'Error: Line 1: Undefined label \'x\'' + }, + + 'x: while (true) { (function () { break; }); }': { + index: 39, + lineNumber: 1, + column: 40, + message: 'Error: Line 1: Illegal break statement' + }, + + 'x: while (true) { (function () { continue; }); }': { + index: 42, + lineNumber: 1, + column: 43, + message: 'Error: Line 1: Illegal continue statement' + }, + + 'x: while (true) { x: while (true) { } }': { + index: 20, + lineNumber: 1, + column: 21, + message: 'Error: Line 1: Label \'x\' has already been declared' + }, + + '(function () { \'use strict\'; delete i; }())': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Delete of an unqualified identifier in strict mode.' + }, + + '(function () { \'use strict\'; with (i); }())': { + index: 28, + lineNumber: 1, + column: 29, + message: 'Error: Line 1: Strict mode code may not include a with statement' + }, + + 'function hello() {\'use strict\'; ({ i: 42, i: 42 }) }': { + index: 47, + lineNumber: 1, + column: 48, + message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; ({ hasOwnProperty: 42, hasOwnProperty: 42 }) }': { + index: 73, + lineNumber: 1, + column: 74, + message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; var eval = 10; }': { + index: 40, + lineNumber: 1, + column: 41, + message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; var arguments = 10; }': { + index: 45, + lineNumber: 1, + column: 46, + message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; try { } catch (eval) { } }': { + index: 51, + lineNumber: 1, + column: 52, + message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; try { } catch (arguments) { } }': { + index: 56, + lineNumber: 1, + column: 57, + message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; eval = 10; }': { + index: 32, + lineNumber: 1, + column: 33, + message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; arguments = 10; }': { + index: 32, + lineNumber: 1, + column: 33, + message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; ++eval; }': { + index: 38, + lineNumber: 1, + column: 39, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; --eval; }': { + index: 38, + lineNumber: 1, + column: 39, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; ++arguments; }': { + index: 43, + lineNumber: 1, + column: 44, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; --arguments; }': { + index: 43, + lineNumber: 1, + column: 44, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; eval++; }': { + index: 36, + lineNumber: 1, + column: 37, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; eval--; }': { + index: 36, + lineNumber: 1, + column: 37, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; arguments++; }': { + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; arguments--; }': { + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }, + + 'function hello() {\'use strict\'; function eval() { } }': { + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; function arguments() { } }': { + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function eval() {\'use strict\'; }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function arguments() {\'use strict\'; }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; (function eval() { }()) }': { + index: 42, + lineNumber: 1, + column: 43, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; (function arguments() { }()) }': { + index: 42, + lineNumber: 1, + column: 43, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + '(function eval() {\'use strict\'; })()': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + '(function arguments() {\'use strict\'; })()': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + 'function hello() {\'use strict\'; ({ s: function eval() { } }); }': { + index: 47, + lineNumber: 1, + column: 48, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }, + + '(function package() {\'use strict\'; })()': { + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() {\'use strict\'; ({ i: 10, set s(eval) { } }); }': { + index: 48, + lineNumber: 1, + column: 49, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; ({ set s(eval) { } }); }': { + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello() {\'use strict\'; ({ s: function s(eval) { } }); }': { + index: 49, + lineNumber: 1, + column: 50, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello(eval) {\'use strict\';}': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello(arguments) {\'use strict\';}': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello() { \'use strict\'; function inner(eval) {} }': { + index: 48, + lineNumber: 1, + column: 49, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function hello() { \'use strict\'; function inner(arguments) {} }': { + index: 48, + lineNumber: 1, + column: 49, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + ' "\\1"; \'use strict\';': { + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { \'use strict\'; "\\1"; }': { + index: 33, + lineNumber: 1, + column: 34, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { \'use strict\'; 021; }': { + index: 33, + lineNumber: 1, + column: 34, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { \'use strict\'; ({ "\\1": 42 }); }': { + index: 36, + lineNumber: 1, + column: 37, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { \'use strict\'; ({ 021: 42 }); }': { + index: 36, + lineNumber: 1, + column: 37, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { "octal directive\\1"; "use strict"; }': { + index: 19, + lineNumber: 1, + column: 20, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { "octal directive\\1"; "octal directive\\2"; "use strict"; }': { + index: 19, + lineNumber: 1, + column: 20, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { "use strict"; function inner() { "octal directive\\1"; } }': { + index: 52, + lineNumber: 1, + column: 53, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }, + + 'function hello() { "use strict"; var implements; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var interface; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var package; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var private; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var protected; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var public; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var static; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var yield; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello() { "use strict"; var let; }': { + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function hello(static) { "use strict"; }': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function static() { "use strict"; }': { + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'var yield': { + index: 4, + lineNumber: 1, + column: 5, + message: 'Error: Line 1: Unexpected token yield' + }, + + 'var let': { + index: 4, + lineNumber: 1, + column: 5, + message: 'Error: Line 1: Unexpected token let' + }, + + '"use strict"; function static() { }': { + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function a(t, t) { "use strict"; }': { + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }, + + 'function a(eval) { "use strict"; }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + 'function a(package) { "use strict"; }': { + index: 11, + lineNumber: 1, + column: 12, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'function a() { "use strict"; function b(t, t) { }; }': { + index: 43, + lineNumber: 1, + column: 44, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }, + + '(function a(t, t) { "use strict"; })': { + index: 15, + lineNumber: 1, + column: 16, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }, + + 'function a() { "use strict"; (function b(t, t) { }); }': { + index: 44, + lineNumber: 1, + column: 45, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }, + + '(function a(eval) { "use strict"; })': { + index: 12, + lineNumber: 1, + column: 13, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }, + + '(function a(package) { "use strict"; })': { + index: 12, + lineNumber: 1, + column: 13, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }, + + 'var': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'let': { + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Unexpected end of input' + }, + + 'const': { + index: 5, + lineNumber: 1, + column: 6, + message: 'Error: Line 1: Unexpected end of input' + } + + }, + + 'API': { + 'parse()': { + call: 'parse', + args: [], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'undefined' + } + }] + } + }, + + 'parse(null)': { + call: 'parse', + args: [null], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: null + } + }] + } + }, + + 'parse(42)': { + call: 'parse', + args: [42], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42 + } + }] + } + }, + + 'parse(true)': { + call: 'parse', + args: [true], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: true + } + }] + } + }, + + 'parse(undefined)': { + call: 'parse', + args: [void 0], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'undefined' + } + }] + } + }, + + 'parse(new String("test"))': { + call: 'parse', + args: [new String('test')], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Identifier', + name: 'test' + } + }] + } + }, + + 'parse(new Number(42))': { + call: 'parse', + args: [new Number(42)], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 42 + } + }] + } + }, + + 'parse(new Boolean(true))': { + call: 'parse', + args: [new Boolean(true)], + result: { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: true + } + }] + } + }, + + 'Syntax': { + property: 'Syntax', + result: { + AssignmentExpression: 'AssignmentExpression', + ArrayExpression: 'ArrayExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement' + } + } + + }, + + 'Tolerant parse': { + 'return': { + type: 'Program', + body: [{ + type: 'ReturnStatement', + 'argument': null, + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + }], + range: [0, 6], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + }, + errors: [{ + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Illegal return statement' + }] + }, + + '(function () { \'use strict\'; with (i); }())': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '\'use strict\'', + range: [15, 27], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 27 } + } + }, + range: [15, 28], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 28 } + } + }, { + type: 'WithStatement', + object: { + type: 'Identifier', + name: 'i', + range: [35, 36], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 36 } + } + }, + body: { + type: 'EmptyStatement', + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }, + range: [29, 38], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 38 } + } + }], + range: [13, 40], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 40 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 40], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 40 } + } + }, + 'arguments': [], + range: [1, 42], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 42 } + } + }, + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 43 } + } + }], + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 43 } + }, + errors: [{ + index: 29, + lineNumber: 1, + column: 30, + message: 'Error: Line 1: Strict mode code may not include a with statement' + }] + }, + + '(function () { \'use strict\'; 021 }())': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'CallExpression', + callee: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '\'use strict\'', + range: [15, 27], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 27 } + } + }, + range: [15, 28], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 28 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 17, + raw: "021", + range: [29, 32], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 32 } + } + }, + range: [29, 33], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }], + range: [13, 34], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [1, 34], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 34 } + } + }, + 'arguments': [], + range: [1, 36], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 37], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 37 } + } + }], + range: [0, 37], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 37 } + }, + errors: [{ + index: 29, + lineNumber: 1, + column: 30, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }] + }, + + '"use strict"; delete x': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UnaryExpression', + operator: 'delete', + argument: { + type: 'Identifier', + name: 'x', + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + prefix: true, + range: [14, 22], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 22 } + } + }, + range: [14, 22], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 22 } + } + }], + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + }, + errors: [{ + index: 22, + lineNumber: 1, + column: 23, + message: 'Error: Line 1: Delete of an unqualified identifier in strict mode.' + }] + }, + + '"use strict"; try {} catch (eval) {}': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'eval', + range: [28, 32], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 32 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + range: [21, 36], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 36 } + } + }], + finalizer: null, + range: [14, 36], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 36 } + } + }], + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + }, + errors: [{ + index: 32, + lineNumber: 1, + column: 33, + message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; try {} catch (arguments) {}': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'TryStatement', + block: { + type: 'BlockStatement', + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + guardedHandlers: [], + handlers: [{ + type: 'CatchClause', + param: { + type: 'Identifier', + name: 'arguments', + range: [28, 37], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 37 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [39, 41], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 41 } + } + }, + range: [21, 41], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 41 } + } + }], + finalizer: null, + range: [14, 41], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 41 } + } + }], + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + }, + errors: [{ + index: 37, + lineNumber: 1, + column: 38, + message: 'Error: Line 1: Catch variable may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; var eval;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'eval', + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + init: null, + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }], + kind: 'var', + range: [14, 23], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 23 } + } + }], + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + }, + errors: [{ + index: 22, + lineNumber: 1, + column: 23, + message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; var arguments;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'arguments', + range: [18, 27], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 27 } + } + }, + init: null, + range: [18, 27], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 27 } + } + }], + kind: 'var', + range: [14, 28], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 28 } + } + }], + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + }, + errors: [{ + index: 27, + lineNumber: 1, + column: 28, + message: 'Error: Line 1: Variable name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; eval = 0;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'eval', + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + range: [14, 22], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 22 } + } + }, + range: [14, 23], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 23 } + } + }], + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + }, + errors: [{ + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode' + }] + }, + + '"use strict"; eval++;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'eval', + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + prefix: false, + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + range: [14, 21], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + }, + errors: [{ + index: 18, + lineNumber: 1, + column: 19, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }] + }, + + '"use strict"; --eval;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'eval', + range: [16, 20], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 20 } + } + }, + prefix: true, + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + range: [14, 21], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + }, + errors: [{ + index: 20, + lineNumber: 1, + column: 21, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }] + }, + + '"use strict"; arguments = 0;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'arguments', + range: [14, 23], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 23 } + } + }, + right: { + type: 'Literal', + value: 0, + raw: '0', + range: [26, 27], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, + range: [14, 27], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 27 } + } + }, + range: [14, 28], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 28 } + } + }], + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + }, + errors: [{ + index: 14, + lineNumber: 1, + column: 15, + message: 'Error: Line 1: Assignment to eval or arguments is not allowed in strict mode' + }] + }, + + '"use strict"; arguments--;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Identifier', + name: 'arguments', + range: [14, 23], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 23 } + } + }, + prefix: false, + range: [14, 25], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 25 } + } + }, + range: [14, 26], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 26 } + } + }], + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + }, + errors: [{ + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Postfix increment/decrement may not have eval or arguments operand in strict mode' + }] + }, + + '"use strict"; ++arguments;': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Identifier', + name: 'arguments', + range: [16, 25], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 25 } + } + }, + prefix: true, + range: [14, 25], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 25 } + } + }, + range: [14, 26], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 26 } + } + }], + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + }, + errors: [{ + index: 25, + lineNumber: 1, + column: 26, + message: 'Error: Line 1: Prefix increment/decrement may not have eval or arguments operand in strict mode' + }] + }, + + + '"use strict";x={y:1,y:1}': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'y', + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + value: { + type: 'Literal', + value: 1, + raw: '1', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + kind: 'init', + range: [16, 19], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 19 } + } + }, { + type: 'Property', + key: { + type: 'Identifier', + name: 'y', + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + value: { + type: 'Literal', + value: 1, + raw: '1', + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + kind: 'init', + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }], + range: [15, 24], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 24 } + } + }, + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }, + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }], + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + }, + errors: [{ + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Duplicate data property in object literal not allowed in strict mode' + }] + }, + + '"use strict"; function eval() {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'eval', + range: [23, 27], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 27 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [30, 32], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 32 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 32], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 32 } + } + }, { + type: 'EmptyStatement', + range: [32, 33], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 33 } + } + }], + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + }, + errors: [{ + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; function arguments() {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'arguments', + range: [23, 32], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 32 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [35, 37], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 37 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 37], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 37 } + } + }, { + type: 'EmptyStatement', + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }], + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + }, + errors: [{ + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; function interface() {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'interface', + range: [23, 32], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 32 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [35, 37], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 37 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 37], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 37 } + } + }, { + type: 'EmptyStatement', + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }], + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + }, + errors: [{ + index: 23, + lineNumber: 1, + column: 24, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }] + }, + + '"use strict"; (function eval() {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'eval', + range: [24, 28], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 28 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [31, 33], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 33], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 33 } + } + }, + range: [14, 35], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 35 } + } + }], + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + }, + errors: [{ + index: 24, + lineNumber: 1, + column: 25, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; (function arguments() {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'arguments', + range: [24, 33], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 33 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 38], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 38 } + } + }, + range: [14, 40], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 40 } + } + }], + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + }, + errors: [{ + index: 24, + lineNumber: 1, + column: 25, + message: 'Error: Line 1: Function name may not be eval or arguments in strict mode' + }] + }, + + '"use strict"; (function interface() {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'interface', + range: [24, 33], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 33 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 38], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 38 } + } + }, + range: [14, 40], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 40 } + } + }], + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + }, + errors: [{ + index: 24, + lineNumber: 1, + column: 25, + message: 'Error: Line 1: Use of future reserved word in strict mode' + }] + }, + + '"use strict"; function f(eval) {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'f', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + params: [{ + type: 'Identifier', + name: 'eval', + range: [25, 29], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 29 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [31, 33], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 33], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 33 } + } + }, { + type: 'EmptyStatement', + range: [33, 34], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 34 } + } + }], + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + }, + errors: [{ + index: 25, + lineNumber: 1, + column: 26, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }] + }, + + '"use strict"; function f(arguments) {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'f', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + params: [{ + type: 'Identifier', + name: 'arguments', + range: [25, 34], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 34 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 38], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 38 } + } + }, { + type: 'EmptyStatement', + range: [38, 39], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 39 } + } + }], + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + }, + errors: [{ + index: 25, + lineNumber: 1, + column: 26, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }] + }, + + '"use strict"; function f(foo, foo) {};': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'f', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + params: [{ + type: 'Identifier', + name: 'foo', + range: [25, 28], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 28 } + } + }, { + type: 'Identifier', + name: 'foo', + range: [31, 34], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 34 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + range: [14, 38], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 38 } + } + }, { + type: 'EmptyStatement', + range: [38, 39], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 39 } + } + }], + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + }, + errors: [{ + index: 31, + lineNumber: 1, + column: 32, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }] + }, + + '"use strict"; (function f(eval) {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'f', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + params: [{ + type: 'Identifier', + name: 'eval', + range: [26, 30], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 30 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [32, 34], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 34], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 34 } + } + }, + range: [14, 36], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 36 } + } + }], + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + }, + errors: [{ + index: 26, + lineNumber: 1, + column: 27, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }] + }, + + + '"use strict"; (function f(arguments) {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'f', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + params: [{ + type: 'Identifier', + name: 'arguments', + range: [26, 35], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 35 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [37, 39], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 39 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 39], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 39 } + } + }, + range: [14, 41], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 41 } + } + }], + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + }, + errors: [{ + index: 26, + lineNumber: 1, + column: 27, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }] + }, + + '"use strict"; (function f(foo, foo) {});': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'FunctionExpression', + id: { + type: 'Identifier', + name: 'f', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + params: [{ + type: 'Identifier', + name: 'foo', + range: [26, 29], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 29 } + } + }, { + type: 'Identifier', + name: 'foo', + range: [32, 35], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 35 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [37, 39], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 39 } + } + }, + rest: null, + generator: false, + expression: false, + range: [15, 39], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 39 } + } + }, + range: [14, 41], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 41 } + } + }], + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + }, + errors: [{ + index: 32, + lineNumber: 1, + column: 33, + message: 'Error: Line 1: Strict mode function may not have duplicate parameter names' + }] + }, + + '"use strict"; x = { set f(eval) {} }' : { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Identifier', + name: 'x', + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + right: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'f', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + value : { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'eval', + range: [26, 30], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 30 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [32, 34], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [32, 34], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 34 } + } + }, + kind: 'set', + range: [20, 34], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 34 } + } + }], + range: [18, 36], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 36 } + } + }, + range: [14, 36], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 36 } + } + }, + range: [14, 36], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 36 } + } + }], + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + }, + errors: [{ + index: 26, + lineNumber: 1, + column: 27, + message: 'Error: Line 1: Parameter name eval or arguments is not allowed in strict mode' + }] + }, + + 'function hello() { "octal directive\\1"; "use strict"; }': { + type: 'Program', + body: [{ + type: 'FunctionDeclaration', + id: { + type: 'Identifier', + name: 'hello', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'octal directive\u0001', + raw: '"octal directive\\1"', + range: [19, 38], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 38 } + } + }, + range: [19, 39], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 39 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [40, 52], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 52 } + } + }, + range: [40, 53], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 53 } + } + }], + range: [17, 55], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 55 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 55], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 55 } + } + }], + range: [0, 55], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 55 } + }, + errors: [{ + index: 19, + lineNumber: 1, + column: 20, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }] + }, + + '"\\1"; \'use strict\';': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: '\u0001', + raw: '"\\1"', + range: [0, 4], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '\'use strict\'', + range: [6, 18], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 18 } + } + }, + range: [6, 19], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + }], + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + }, + errors: [{ + index: 0, + lineNumber: 1, + column: 1, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }] + }, + + '"use strict"; var x = { 014: 3}': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + init: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Literal', + value: 12, + raw: '014', + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + value: { + type: 'Literal', + value: 3, + raw: '3', + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + kind: 'init', + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }], + range: [22, 31], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 31 } + } + }, + range: [18, 31], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 31 } + } + }], + kind: 'var', + range: [14, 31], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 31 } + } + }], + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + }, + errors: [{ + index: 24, + lineNumber: 1, + column: 25, + message: 'Error: Line 1: Octal literals are not allowed in strict mode.' + }] + }, + + '"use strict"; var x = { get i() {}, get i() {} }': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + init: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [28, 29], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [32, 34], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + generator: false, + expression: false, + range: [32, 34], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 34 } + } + }, + kind: 'get', + range: [24, 34], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 34 } + } + }, { + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [40, 41], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 41 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [44, 46], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 46 } + } + }, + rest: null, + generator: false, + expression: false, + range: [44, 46], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 46 } + } + }, + kind: 'get', + range: [36, 46], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 46 } + } + }], + range: [22, 48], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 48 } + } + }, + range: [18, 48], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 48 } + } + }], + kind: 'var', + range: [14, 48], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 48 } + } + }], + range: [0, 48], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 48 } + }, + errors: [{ + index: 46, + lineNumber: 1, + column: 47, + message: 'Error: Line 1: Object literal may not have multiple get/set accessors with the same name' + }] + }, + + '"use strict"; var x = { i: 42, get i() {} }': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + init: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [27, 29], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 29 } + } + }, + kind: 'init', + range: [24, 29], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 29 } + } + }, { + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [35, 36], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 36 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [39, 41], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 41 } + } + }, + rest: null, + generator: false, + expression: false, + range: [39, 41], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 41 } + } + }, + kind: 'get', + range: [31, 41], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 41 } + } + }], + range: [22, 43], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 43 } + } + }, + range: [18, 43], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 43 } + } + }], + kind: 'var', + range: [14, 43], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 43 } + } + }], + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 43 } + }, + errors: [{ + index: 41, + lineNumber: 1, + column: 42, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }] + }, + + '"use strict"; var x = { set i(x) {}, i: 42 }': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: 'use strict', + raw: '"use strict"', + range: [0, 12], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, { + type: 'VariableDeclaration', + declarations: [{ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: 'x', + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + init: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [28, 29], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [{ + type: 'Identifier', + name: 'x', + range: [30, 31], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 31 } + } + }], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + generator: false, + expression: false, + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + kind: 'set', + range: [24, 35], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 35 } + } + }, { + type: 'Property', + key: { + type: 'Identifier', + name: 'i', + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }, + value: { + type: 'Literal', + value: 42, + raw: '42', + range: [40, 42], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 42 } + } + }, + kind: 'init', + range: [37, 42], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 42 } + } + }], + range: [22, 44], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 44 } + } + }, + range: [18, 44], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 44 } + } + }], + kind: 'var', + range: [14, 44], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 44 } + } + }], + range: [0, 44], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 44 } + }, + errors: [{ + index: 42, + lineNumber: 1, + column: 43, + message: 'Error: Line 1: Object literal may not have data and accessor property with the same name' + }] + + + }, + + '({ set s() { } })': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'ObjectExpression', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 's', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + value: { + type: 'FunctionExpression', + id: null, + params: [], + defaults: [], + body: { + type: 'BlockStatement', + body: [], + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + rest: null, + generator: false, + expression: false, + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + kind: 'set', + range: [3, 14], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 14 } + } + }], + range: [1, 16], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }], + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + }, + errors: [{ + index: 9, + lineNumber: 1, + column: 10, + message: 'Error: Line 1: Unexpected token )' + }] + }, + + 'foo("bar") = baz': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'foo', + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + 'arguments': [{ + type: 'Literal', + value: 'bar', + raw: '"bar"', + range: [4, 9], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }], + range: [0, 10], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + }, + right: { + type: 'Identifier', + name: 'baz', + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }], + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + }, + errors: [{ + index: 10, + lineNumber: 1, + column: 11, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }] + }, + + '1 = 2': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'AssignmentExpression', + operator: '=', + left: { + type: 'Literal', + value: 1, + raw: '1', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: 'Literal', + value: 2, + raw: '2', + range: [4, 5], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + }, + errors: [{ + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }] + }, + + '3++': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '++', + argument: { + type: 'Literal', + value: 3, + raw: '3', + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + prefix: false, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + }, + errors: [{ + index: 1, + lineNumber: 1, + column: 2, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }] + }, + + '--4': { + type: 'Program', + body: [{ + type: 'ExpressionStatement', + expression: { + type: 'UpdateExpression', + operator: '--', + argument: { + type: 'Literal', + value: 4, + raw: '4', + range: [2, 3], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + prefix: true, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + }, + errors: [{ + index: 3, + lineNumber: 1, + column: 4, + message: 'Error: Line 1: Invalid left-hand side in assignment' + }] + }, + + 'for (5 in []) {}': { + type: 'Program', + body: [{ + type: 'ForInStatement', + left: { + type: 'Literal', + value: 5, + raw: '5', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: 'ArrayExpression', + elements: [], + range: [10, 12], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 12 } + } + }, + body: { + type: 'BlockStatement', + body: [], + range: [14, 16], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 16 } + } + }, + each: false, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }], + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + }, + errors: [{ + index: 6, + lineNumber: 1, + column: 7, + message: 'Error: Line 1: Invalid left-hand side in for-in' + }] + } + + + } +}; + diff --git a/node_modules/grunt/node_modules/js-yaml/package.json b/node_modules/grunt/node_modules/js-yaml/package.json new file mode 100644 index 000000000..8a090e6c9 --- /dev/null +++ b/node_modules/grunt/node_modules/js-yaml/package.json @@ -0,0 +1,64 @@ +{ + "name": "js-yaml", + "version": "2.0.5", + "description": "YAML 1.2 parser and serializer", + "keywords": [ + "yaml", + "parser", + "serializer", + "pyyaml" + ], + "homepage": "https://github.com/nodeca/js-yaml", + "author": { + "name": "Dervus Grim", + "email": "dervus@lavabit.com" + }, + "contributors": [ + { + "name": "Aleksey V Zapparov", + "email": "ixti@member.fsf.org", + "url": "http://www.ixti.net/" + }, + { + "name": "Martin Grenfell", + "email": "martin.grenfell@gmail.com", + "url": "http://got-ravings.blogspot.com" + } + ], + "bugs": { + "url": "https://github.com/nodeca/js-yaml/issues" + }, + "license": { + "type": "MIT", + "url": "https://github.com/nodeca/js-yaml/blob/master/LICENSE" + }, + "repository": { + "type": "git", + "url": "git://github.com/nodeca/js-yaml.git" + }, + "main": "./index.js", + "bin": { + "js-yaml": "bin/js-yaml.js" + }, + "scripts": { + "test": "make test" + }, + "dependencies": { + "argparse": "~ 0.1.11", + "esprima": "~ 1.0.2" + }, + "devDependencies": { + "mocha": "*" + }, + "engines": { + "node": ">= 0.6.0" + }, + "readme": "JS-YAML - YAML 1.2 parser and serializer for JavaScript\n=======================================================\n\n[![Build Status](https://secure.travis-ci.org/nodeca/js-yaml.png)](http://travis-ci.org/nodeca/js-yaml)\n\n[Online Demo](http://nodeca.github.com/js-yaml/)\n\n\nThis is an implementation of [YAML](http://yaml.org/), a human friendly data\nserialization language. Started as [PyYAML](http://pyyaml.org/) port, it was\ncompletely rewritten from scratch. Now it's very fast, and supports 1.2 spec.\n\n\nBreaking changes in 1.x.x -> 2.0.x\n----------------------------------\n\nIf your have not used __custom__ tags or loader classes - no changes needed. Just\nupgrade library and enjoy high parse speed.\n\nIn other case, you should rewrite your tag constructors and custom loader\nclasses, to conform new schema-based API. See\n[examples](https://github.com/nodeca/js-yaml/tree/master/examples) and\n[wiki](https://github.com/nodeca/js-yaml/wiki) for details.\nNote, that parser internals were completely rewritten.\n\n\nInstallation\n------------\n\n### YAML module for node.js\n\n```\nnpm install js-yaml\n```\n\n\n### CLI executable\n\nIf you want to inspect your YAML files from CLI, install js-yaml globally:\n\n```\nnpm install js-yaml -g\n```\n\n#### Usage\n\n```\nusage: js-yaml [-h] [-v] [-c] [-j] [-t] file\n\nPositional arguments:\n file File with YAML document(s)\n\nOptional arguments:\n -h, --help Show this help message and exit.\n -v, --version Show program's version number and exit.\n -c, --compact Display errors in compact mode\n -j, --to-json Output a non-funky boring JSON\n -t, --trace Show stack trace on error\n```\n\n\n### Bundled YAML library for browsers\n\n``` html\n\n\n```\n\nBrowser support was done mostly for online demo. If you find any errors - feel\nfree to send pull requests with fixes. Also note, that IE and other old browsers\nneeds [es5-shims](https://github.com/kriskowal/es5-shim) to operate.\n\n\nAPI\n---\n\nHere we cover the most 'useful' methods. If you need advanced details (creating\nyour own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and\n[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more\ninfo.\n\nIn node.js JS-YAML automatically registers handlers for `.yml` and `.yaml`\nfiles. You can load them just with `require`. That's mostly equivalent to\ncalling `load()` on fetched content of a file. Just with one string!\n\n``` javascript\nrequire('js-yaml');\n\n// Get document, or throw exception on error\ntry {\n var doc = require('/home/ixti/example.yml');\n console.log(doc);\n} catch (e) {\n console.log(e);\n}\n```\n\n\n### load (string [ , options ])\n\nParses `string` as single YAML document. Returns a JavaScript object or throws\n`YAMLException` on error.\n\nNOTE: This function **does not** understands multi-document sources, it throws\nexception on those.\n\noptions:\n\n- `filename` _(default: null)_ - string to be used as a file path in\n error/warning messages.\n- `strict` _(default - false)_ makes the loader to throw errors instead of\n warnings.\n- `schema` _(default: `DEFAULT_SCHEMA`)_ - specifies a schema to use.\n\n\n### loadAll (string, iterator [ , options ])\n\nSame as `load()`, but understands multi-document sources and apply `iterator` to\neach document.\n\n``` javascript\nvar yaml = require('js-yaml');\n\nyaml.loadAll(data, function (doc) {\n console.log(doc);\n});\n```\n\n\n### safeLoad (string [ , options ])\n\nSame as `load()` but uses `SAFE_SCHEMA` by default - only recommended tags of\nYAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`).\n\n\n### safeLoadAll (string, iterator [ , options ])\n\nSame as `loadAll()` but uses `SAFE_SCHEMA` by default - only recommended tags of\nYAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`).\n\n\n### dump (object [ , options ])\n\nSerializes `object` as YAML document.\n\noptions:\n\n- `indent` _(default: 2)_ - indentation width to use (in spaces).\n- `flowLevel` (default: -1) - specifies level of nesting, when to switch from\n block to flow style for collections. -1 means block style everwhere\n- `styles` - \"tag\" => \"style\" map. Each tag may have own set of styles.\n- `schema` _(default: `DEFAULT_SCHEMA`)_ specifies a schema to use.\n\nstyles:\n\n``` none\n!!null\n \"canonical\" => \"~\"\n\n!!int\n \"binary\" => \"0b1\", \"0b101010\", \"0b1110001111010\"\n \"octal\" => \"01\", \"052\", \"016172\"\n \"decimal\" => \"1\", \"42\", \"7290\"\n \"hexadecimal\" => \"0x1\", \"0x2A\", \"0x1C7A\"\n\n!!null, !!bool, !!float\n \"lowercase\" => \"null\", \"true\", \"false\", \".nan\", '.inf'\n \"uppercase\" => \"NULL\", \"TRUE\", \"FALSE\", \".NAN\", '.INF'\n \"camelcase\" => \"Null\", \"True\", \"False\", \".NaN\", '.Inf'\n```\n\nBy default, !!int uses `decimal`, and !!null, !!bool, !!float use `lowercase`.\n\n\n### safeDump (object [ , options ])\n\nSame as `dump()` but uses `SAFE_SCHEMA` by default - only recommended tags of\nYAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`).\n\n\nSupported YAML types\n--------------------\n\nThe list of standard YAML tags and corresponding JavaScipt types. See also\n[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and\n[YAML types repository](http://yaml.org/type/).\n\n```\n!!null '' # null\n!!bool 'yes' # bool\n!!int '3...' # number\n!!float '3.14...' # number\n!!binary '...base64...' # buffer\n!!timestamp 'YYYY-...' # date\n!!omap [ ... ] # array of key-value pairs\n!!pairs [ ... ] # array or array pairs\n!!set { ... } # array of objects with given keys and null values\n!!str '...' # string\n!!seq [ ... ] # array\n!!map { ... } # object\n```\n\n**JavaScript-specific tags**\n\n```\n!!js/regexp /pattern/gim # RegExp\n!!js/undefined '' # Undefined\n!!js/function 'function () {...}' # Function\n```\n\n\n\n\n## Caveats\n\nNote, that you use arrays or objects as key in JS-YAML. JS do not allows objects\nor array as keys, and stringifies (by calling .toString method) them at the\nmoment of adding them.\n\n``` yaml\n---\n? [ foo, bar ]\n: - baz\n? { foo: bar }\n: - baz\n - baz\n```\n\n``` javascript\n{ \"foo,bar\": [\"baz\"], \"[object Object]\": [\"baz\", \"baz\"] }\n```\n\nAlso, reading of properties on implicit block mapping keys is not supported yet.\nSo, the following YAML document cannot be loaded.\n\n``` yaml\n&anchor foo:\n foo: bar\n *anchor: duplicate key\n baz: bat\n *anchor: duplicate key\n```\n\n## License\n\nView the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file\n(MIT).\n", + "readmeFilename": "README.md", + "_id": "js-yaml@2.0.5", + "dist": { + "shasum": "e2b8235a4d4283a2c5ac3f8fd029f7402aa6d030" + }, + "_from": "js-yaml@~2.0.2", + "_resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz" +} diff --git a/node_modules/grunt/node_modules/lodash/README.md b/node_modules/grunt/node_modules/lodash/README.md new file mode 100644 index 000000000..55dae80fe --- /dev/null +++ b/node_modules/grunt/node_modules/lodash/README.md @@ -0,0 +1,140 @@ +# Lo-Dash v0.9.2 + +A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features). + +## Download + + * [Development build](https://raw.github.com/lodash/lodash/0.9.2/lodash.js) + * [Production build](https://raw.github.com/lodash/lodash/0.9.2/lodash.min.js) + * [Underscore build](https://raw.github.com/lodash/lodash/0.9.2/lodash.underscore.min.js) tailored for projects already using Underscore + * CDN copies of ≤ v0.9.2’s [Production](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min.js), [Underscore](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.underscore.min.js), and [Development](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.js) builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/) + * For optimal file size, [create a custom build](http://lodash.com/custom-builds) with only the features you need + +## Dive in + +We’ve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests). + +Create your own benchmarks at [jsPerf](http://jsperf.com), or [search](http://jsperf.com/search?q=lodash) for existing ones. + +For a list of upcoming features, check out our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap). + +## Screencasts + +For more information check out these screencasts over Lo-Dash: + + * [Introducing Lo-Dash](https://vimeo.com/44154599) + * [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601) + * [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600) + * [Unit testing in Lo-Dash](https://vimeo.com/45865290) + * [Lo-Dash’s approach to native method use](https://vimeo.com/48576012) + +## Features + + * AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.) + * [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning + * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument + * [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early + * [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties + * [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties + * [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor + * [_.lateBind](http://lodash.com/docs#lateBind) for late binding + * [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend) + * [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding + * [_.pick](http://lodash.com/docs#pick) and [_.omit](http://lodash.com/docs#omit) accepts `callback` and `thisArg` arguments + * [_.template](http://lodash.com/docs#template) supports [ES6 delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6) and utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging + * [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray), + [and more…](http://lodash.com/docs "_.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings + +## Support + +Lo-Dash has been tested in at least Chrome 5~23, Firefox 1~16, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.14, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5. + +## Installation and usage + +In browsers: + +```html + +``` + +Using [npm](http://npmjs.org/): + +```bash +npm install lodash + +npm install -g lodash +npm link lodash +``` + +In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/): + +```js +var _ = require('lodash'); +``` + +**Note:** If Lo-Dash is installed globally, [run `npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it. + +In [RingoJS v0.7.0-](http://ringojs.org/): + +```js +var _ = require('lodash')._; +``` + +In [Rhino](http://www.mozilla.org/rhino/): + +```js +load('lodash.js'); +``` + +In an AMD loader like [RequireJS](http://requirejs.org/): + +```js +require({ + 'paths': { + 'underscore': 'path/to/lodash' + } +}, +['underscore'], function(_) { + console.log(_.VERSION); +}); +``` + +## Resolved Underscore.js issues + + * Allow iteration of objects with a `length` property [[#799](https://github.com/documentcloud/underscore/pull/799), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L545-551)] + * Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L558-582)] + * Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L140-146)] + * `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L747-752)] + * `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L828-840)] + * `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L921-923)] + * `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L1337-1340)] + +## Release Notes + +### v0.9.2 + + * Added `fromIndex` argument to `_.contains` + * Added `moduleId` build option + * Added Closure Compiler *“simple”* optimizations to the build process + * Added support for strings in `_.max` and `_.min` + * Added support for ES6 template delimiters to `_.template` + * Ensured re-minification of Lo-Dash by third parties avoids Closure Compiler bugs + * Optimized `_.every`, `_.find`, `_.some`, and `_.uniq` + +The full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog). + +## BestieJS + +Lo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. + +## Author + +| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") | +|---| +| [John-David Dalton](http://allyoucanleet.com/) | + +## Contributors + +| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz "Follow @BlaineBublitz on Twitter") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") | +|---|---|---| +| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) | diff --git a/node_modules/grunt/node_modules/lodash/lodash.js b/node_modules/grunt/node_modules/lodash/lodash.js new file mode 100644 index 000000000..9eae931c2 --- /dev/null +++ b/node_modules/grunt/node_modules/lodash/lodash.js @@ -0,0 +1,4258 @@ +/*! + * Lo-Dash v0.9.2 + * (c) 2012 John-David Dalton + * Based on Underscore.js 1.4.2 + * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. + * Available under MIT license + */ +;(function(window, undefined) { + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `global` and use it as `window` */ + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal) { + window = freeGlobal; + } + + /** Used for array and object method references */ + var arrayRef = [], + // avoid a Closure Compiler bug by creatively creating an object + objectRef = new function(){}; + + /** Used to generate unique IDs */ + var idCounter = 0; + + /** Used internally to indicate various things */ + var indicatorObject = objectRef; + + /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */ + var largeArraySize = 30; + + /** Used to restore the original `_` reference in `noConflict` */ + var oldDash = window._; + + /** Used to detect template delimiter values that require a with-statement */ + var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/; + + /** Used to match HTML entities */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g; + + /** Used to match empty string literals in compiled template source */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match regexp flags from their coerced string values */ + var reFlags = /\w*$/; + + /** Used to insert the data object variable into compiled template source */ + var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g; + + /** Used to detect if a method is native */ + var reNative = RegExp('^' + + (objectRef.valueOf + '') + .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&') + .replace(/valueOf|for [^\]]+/g, '.+?') + '$' + ); + + /** + * Used to match ES6 template delimiters + * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6 + */ + var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)}/g; + + /** Used to match "interpolate" template delimiters */ + var reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to ensure capturing order of template delimiters */ + var reNoMatch = /($^)/; + + /** Used to match HTML characters */ + var reUnescapedHtml = /[&<>"']/g; + + /** Used to match unescaped characters in compiled string literals */ + var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + + /** Used to fix the JScript [[DontEnum]] bug */ + var shadowed = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' + ]; + + /** Used to make template sourceURLs easier to identify */ + var templateCounter = 0; + + /** Native method shortcuts */ + var ceil = Math.ceil, + concat = arrayRef.concat, + floor = Math.floor, + getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, + hasOwnProperty = objectRef.hasOwnProperty, + push = arrayRef.push, + propertyIsEnumerable = objectRef.propertyIsEnumerable, + slice = arrayRef.slice, + toString = objectRef.toString; + + /* Native method shortcuts for methods with the same name as other `lodash` methods */ + var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind, + nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, + nativeIsFinite = window.isFinite, + nativeIsNaN = window.isNaN, + nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys, + nativeMax = Math.max, + nativeMin = Math.min, + nativeRandom = Math.random; + + /** `Object#toString` result shortcuts */ + var argsClass = '[object Arguments]', + arrayClass = '[object Array]', + boolClass = '[object Boolean]', + dateClass = '[object Date]', + funcClass = '[object Function]', + numberClass = '[object Number]', + objectClass = '[object Object]', + regexpClass = '[object RegExp]', + stringClass = '[object String]'; + + /** + * Detect the JScript [[DontEnum]] bug: + * + * In IE < 9 an objects own properties, shadowing non-enumerable ones, are + * made non-enumerable as well. + */ + var hasDontEnumBug; + + /** Detect if own properties are iterated after inherited properties (IE < 9) */ + var iteratesOwnLast; + + /** + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * incorrectly: + * + * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` + * and `splice()` functions that fail to remove the last element, `value[0]`, + * of array-like objects even though the `length` property is set to `0`. + * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + */ + var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 }, + arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]); + + /** Detect if an `arguments` object's indexes are non-enumerable (IE < 9) */ + var noArgsEnum = true; + + (function() { + var props = []; + function ctor() { this.x = 1; } + ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var prop in new ctor) { props.push(prop); } + for (prop in arguments) { noArgsEnum = !prop; } + + hasDontEnumBug = !/valueOf/.test(props); + iteratesOwnLast = props[0] != 'x'; + }(1)); + + /** Detect if an `arguments` object's [[Class]] is unresolvable (Firefox < 4, IE < 9) */ + var noArgsClass = !isArguments(arguments); + + /** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */ + var noArraySliceOnStrings = slice.call('x')[0] != 'x'; + + /** + * Detect lack of support for accessing string characters by index: + * + * IE < 8 can't access characters by index and IE 8 can only access + * characters by index on string literals. + */ + var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx'; + + /** + * Detect if a node's [[Class]] is unresolvable (IE < 9) + * and that the JS engine won't error when attempting to coerce an object to + * a string without a `toString` property value of `typeof` "function". + */ + try { + var noNodeClass = ({ 'toString': 0 } + '', toString.call(window.document || 0) == objectClass); + } catch(e) { } + + /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */ + var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera)); + + /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */ + var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent); + + /** + * Detect if sourceURL syntax is usable without erroring: + * + * The JS engine in Adobe products, like InDesign, will throw a syntax error + * when it encounters a single line comment beginning with the `@` symbol. + * + * The JS engine in Narwhal will generate the function `function anonymous(){//}` + * and throw a syntax error. + * + * Avoid comments beginning `@` symbols in IE because they are part of its + * non-standard conditional compilation support. + * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx + */ + try { + var useSourceURL = (Function('//@')(), !window.attachEvent); + } catch(e) { } + + /** Used to identify object classifications that `_.clone` supports */ + var cloneableClasses = {}; + cloneableClasses[argsClass] = cloneableClasses[funcClass] = false; + cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] = + cloneableClasses[stringClass] = true; + + /** Used to determine if values are of the language type Object */ + var objectTypes = { + 'boolean': false, + 'function': true, + 'object': true, + 'number': false, + 'string': false, + 'undefined': false + }; + + /** Used to escape characters for inclusion in compiled string literals */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /*--------------------------------------------------------------------------*/ + + /** + * The `lodash` function. + * + * @name _ + * @constructor + * @category Chaining + * @param {Mixed} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns a `lodash` instance. + */ + function lodash(value) { + // exit early if already wrapped + if (value && value.__wrapped__) { + return value; + } + // allow invoking `lodash` without the `new` operator + if (!(this instanceof lodash)) { + return new lodash(value); + } + this.__wrapped__ = value; + } + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in + * embedded Ruby (ERB). Change the following template settings to use alternative + * delimiters. + * + * @static + * @memberOf _ + * @type Object + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @static + * @memberOf _.templateSettings + * @type RegExp + */ + 'escape': /<%-([\s\S]+?)%>/g, + + /** + * Used to detect code to be evaluated. + * + * @static + * @memberOf _.templateSettings + * @type RegExp + */ + 'evaluate': /<%([\s\S]+?)%>/g, + + /** + * Used to detect `data` property values to inject. + * + * @static + * @memberOf _.templateSettings + * @type RegExp + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @static + * @memberOf _.templateSettings + * @type String + */ + 'variable': '' + }; + + /*--------------------------------------------------------------------------*/ + + /** + * The template used to create iterator functions. + * + * @private + * @param {Obect} data The data object used to populate the text. + * @returns {String} Returns the interpolated text. + */ + var iteratorTemplate = template( + // conditional strict mode + '<% if (obj.useStrict) { %>\'use strict\';\n<% } %>' + + + // the `iteratee` may be reassigned by the `top` snippet + 'var index, value, iteratee = <%= firstArg %>, ' + + // assign the `result` variable an initial value + 'result = <%= firstArg %>;\n' + + // exit early if the first argument is falsey + 'if (!<%= firstArg %>) return result;\n' + + // add code before the iteration branches + '<%= top %>;\n' + + + // array-like iteration: + '<% if (arrayLoop) { %>' + + 'var length = iteratee.length; index = -1;\n' + + 'if (typeof length == \'number\') {' + + + // add support for accessing string characters by index if needed + ' <% if (noCharByIndex) { %>\n' + + ' if (isString(iteratee)) {\n' + + ' iteratee = iteratee.split(\'\')\n' + + ' }' + + ' <% } %>\n' + + + // iterate over the array-like value + ' while (++index < length) {\n' + + ' value = iteratee[index];\n' + + ' <%= arrayLoop %>\n' + + ' }\n' + + '}\n' + + 'else {' + + + // object iteration: + // add support for iterating over `arguments` objects if needed + ' <% } else if (noArgsEnum) { %>\n' + + ' var length = iteratee.length; index = -1;\n' + + ' if (length && isArguments(iteratee)) {\n' + + ' while (++index < length) {\n' + + ' value = iteratee[index += \'\'];\n' + + ' <%= objectLoop %>\n' + + ' }\n' + + ' } else {' + + ' <% } %>' + + + // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + // (if the prototype or a property on the prototype has been set) + // incorrectly sets a function's `prototype` property [[Enumerable]] + // value to `true`. Because of this Lo-Dash standardizes on skipping + // the the `prototype` property of functions regardless of its + // [[Enumerable]] value. + ' <% if (!hasDontEnumBug) { %>\n' + + ' var skipProto = typeof iteratee == \'function\' && \n' + + ' propertyIsEnumerable.call(iteratee, \'prototype\');\n' + + ' <% } %>' + + + // iterate own properties using `Object.keys` if it's fast + ' <% if (isKeysFast && useHas) { %>\n' + + ' var ownIndex = -1,\n' + + ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' + + ' length = ownProps.length;\n\n' + + ' while (++ownIndex < length) {\n' + + ' index = ownProps[ownIndex];\n' + + ' <% if (!hasDontEnumBug) { %>if (!(skipProto && index == \'prototype\')) {\n <% } %>' + + ' value = iteratee[index];\n' + + ' <%= objectLoop %>\n' + + ' <% if (!hasDontEnumBug) { %>}\n<% } %>' + + ' }' + + + // else using a for-in loop + ' <% } else { %>\n' + + ' for (index in iteratee) {<%' + + ' if (!hasDontEnumBug || useHas) { %>\n if (<%' + + ' if (!hasDontEnumBug) { %>!(skipProto && index == \'prototype\')<% }' + + ' if (!hasDontEnumBug && useHas) { %> && <% }' + + ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' + + ' %>) {' + + ' <% } %>\n' + + ' value = iteratee[index];\n' + + ' <%= objectLoop %>;' + + ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' + + ' }' + + ' <% } %>' + + + // Because IE < 9 can't set the `[[Enumerable]]` attribute of an + // existing property and the `constructor` property of a prototype + // defaults to non-enumerable, Lo-Dash skips the `constructor` + // property when it infers it's iterating over a `prototype` object. + ' <% if (hasDontEnumBug) { %>\n\n' + + ' var ctor = iteratee.constructor;\n' + + ' <% for (var k = 0; k < 7; k++) { %>\n' + + ' index = \'<%= shadowed[k] %>\';\n' + + ' if (<%' + + ' if (shadowed[k] == \'constructor\') {' + + ' %>!(ctor && ctor.prototype === iteratee) && <%' + + ' } %>hasOwnProperty.call(iteratee, index)) {\n' + + ' value = iteratee[index];\n' + + ' <%= objectLoop %>\n' + + ' }' + + ' <% } %>' + + ' <% } %>' + + ' <% if (arrayLoop || noArgsEnum) { %>\n}<% } %>\n' + + + // add code to the bottom of the iteration function + '<%= bottom %>;\n' + + // finally, return the `result` + 'return result' + ); + + /** + * Reusable iterator options shared by `forEach`, `forIn`, and `forOwn`. + */ + var forEachIteratorOptions = { + 'args': 'collection, callback, thisArg', + 'top': 'callback = createCallback(callback, thisArg)', + 'arrayLoop': 'if (callback(value, index, collection) === false) return result', + 'objectLoop': 'if (callback(value, index, collection) === false) return result' + }; + + /** Reusable iterator options for `defaults`, and `extend` */ + var extendIteratorOptions = { + 'useHas': false, + 'args': 'object', + 'top': + 'for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {\n' + + ' if (iteratee = arguments[argsIndex]) {', + 'objectLoop': 'result[index] = value', + 'bottom': ' }\n}' + }; + + /** Reusable iterator options for `forIn` and `forOwn` */ + var forOwnIteratorOptions = { + 'arrayLoop': null + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function optimized to search large arrays for a given `value`, + * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`. + * + * @private + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=0] The index to search from. + * @param {Number} [largeSize=30] The length at which an array is considered large. + * @returns {Boolean} Returns `true` if `value` is found, else `false`. + */ + function cachedContains(array, fromIndex, largeSize) { + fromIndex || (fromIndex = 0); + + var length = array.length, + isLarge = (length - fromIndex) >= (largeSize || largeArraySize); + + if (isLarge) { + var cache = {}, + index = fromIndex - 1; + + while (++index < length) { + // manually coerce `value` to a string because `hasOwnProperty`, in some + // older versions of Firefox, coerces objects incorrectly + var key = array[index] + ''; + (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]); + } + } + return function(value) { + if (isLarge) { + var key = value + ''; + return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1; + } + return indexOf(array, value, fromIndex) > -1; + } + } + + /** + * Used by `_.max` and `_.min` as the default `callback` when a given + * `collection` is a string value. + * + * @private + * @param {String} value The character to inspect. + * @returns {Number} Returns the code unit of given character. + */ + function charAtCallback(value) { + return value.charCodeAt(0); + } + + /** + * Used by `sortBy` to compare transformed `collection` values, stable sorting + * them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {Number} Returns the sort order indicator of `1` or `-1`. + */ + function compareAscending(a, b) { + var ai = a.index, + bi = b.index; + + a = a.criteria; + b = b.criteria; + + // ensure a stable sort in V8 and other engines + // http://code.google.com/p/v8/issues/detail?id=90 + if (a !== b) { + if (a > b || a === undefined) { + return 1; + } + if (a < b || b === undefined) { + return -1; + } + } + return ai < bi ? -1 : 1; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any `partailArgs` to the arguments passed + * to the bound function. + * + * @private + * @param {Function|String} func The function to bind or the method name. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Array} partialArgs An array of arguments to be partially applied. + * @returns {Function} Returns the new bound function. + */ + function createBound(func, thisArg, partialArgs) { + var isFunc = isFunction(func), + isPartial = !partialArgs, + methodName = func; + + // juggle arguments + if (isPartial) { + partialArgs = thisArg; + } + + function bound() { + // `Function#bind` spec + // http://es5.github.com/#x15.3.4.5 + var args = arguments, + thisBinding = isPartial ? this : thisArg; + + if (!isFunc) { + func = thisArg[methodName]; + } + if (partialArgs.length) { + args = args.length + ? partialArgs.concat(slice.call(args)) + : partialArgs; + } + if (this instanceof bound) { + // get `func` instance if `bound` is invoked in a `new` expression + noop.prototype = func.prototype; + thisBinding = new noop; + + // mimic the constructor's `return` behavior + // http://es5.github.com/#x13.2.2 + var result = func.apply(thisBinding, args); + return isObject(result) + ? result + : thisBinding + } + return func.apply(thisBinding, args); + } + return bound; + } + + /** + * Produces an iteration callback bound to an optional `thisArg`. If `func` is + * a property name, the callback will return the property value for a given element. + * + * @private + * @param {Function|String} [func=identity|property] The function called per + * iteration or property name to query. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Function} Returns a callback function. + */ + function createCallback(func, thisArg) { + if (!func) { + return identity; + } + if (typeof func != 'function') { + return function(object) { + return object[func]; + }; + } + if (thisArg !== undefined) { + return function(value, index, object) { + return func.call(thisArg, value, index, object); + }; + } + return func; + } + + /** + * Creates compiled iteration functions. + * + * @private + * @param {Object} [options1, options2, ...] The compile options object(s). + * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop. + * args - A string of comma separated arguments the iteration function will accept. + * top - A string of code to execute before the iteration branches. + * arrayLoop - A string of code to execute in the array loop. + * objectLoop - A string of code to execute in the object loop. + * bottom - A string of code to execute after the iteration branches. + * + * @returns {Function} Returns the compiled function. + */ + function createIterator() { + var data = { + 'arrayLoop': '', + 'bottom': '', + 'hasDontEnumBug': hasDontEnumBug, + 'isKeysFast': isKeysFast, + 'objectLoop': '', + 'noArgsEnum': noArgsEnum, + 'noCharByIndex': noCharByIndex, + 'shadowed': shadowed, + 'top': '', + 'useHas': true + }; + + // merge options into a template data object + for (var object, index = 0; object = arguments[index]; index++) { + for (var key in object) { + data[key] = object[key]; + } + } + var args = data.args; + data.firstArg = /^[^,]+/.exec(args)[0]; + + // create the function factory + var factory = Function( + 'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' + + 'nativeKeys, propertyIsEnumerable', + 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' + ); + // return the compiled function + return factory( + createCallback, hasOwnProperty, isArguments, isString, objectTypes, + nativeKeys, propertyIsEnumerable + ); + } + + /** + * Used by `template` to escape characters for inclusion in compiled + * string literals. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeStringChar(match) { + return '\\' + stringEscapes[match]; + } + + /** + * Used by `escape` to convert characters to HTML entities. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } + + /** + * A no-operation function. + * + * @private + */ + function noop() { + // no operation performed + } + + /** + * Used by `unescape` to convert HTML entities to characters. + * + * @private + * @param {String} match The matched character to unescape. + * @returns {String} Returns the unescaped character. + */ + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Checks if `value` is an `arguments` object. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`. + * @example + * + * (function() { return _.isArguments(arguments); })(1, 2, 3); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + function isArguments(value) { + return toString.call(value) == argsClass; + } + // fallback for browsers that can't detect `arguments` objects by [[Class]] + if (noArgsClass) { + isArguments = function(value) { + return value ? hasOwnProperty.call(value, 'callee') : false; + }; + } + + /** + * Iterates over `object`'s own and inherited enumerable properties, executing + * the `callback` for each property. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, key, object). Callbacks may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * function Dog(name) { + * this.name = name; + * } + * + * Dog.prototype.bark = function() { + * alert('Woof, woof!'); + * }; + * + * _.forIn(new Dog('Dagny'), function(value, key) { + * alert(key); + * }); + * // => alerts 'name' and 'bark' (order is not guaranteed) + */ + var forIn = createIterator(forEachIteratorOptions, forOwnIteratorOptions, { + 'useHas': false + }); + + /** + * Iterates over `object`'s own enumerable properties, executing the `callback` + * for each property. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, key, object). Callbacks may exit iteration early by explicitly + * returning `false`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * alert(key); + * }); + * // => alerts '0', '1', and 'length' (order is not guaranteed) + */ + var forOwn = createIterator(forEachIteratorOptions, forOwnIteratorOptions); + + /** + * A fallback implementation of `isPlainObject` that checks if a given `value` + * is an object created by the `Object` constructor, assuming objects created + * by the `Object` constructor have no inherited enumerable properties and that + * there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`. + */ + function shimIsPlainObject(value) { + // avoid non-objects and false positives for `arguments` objects + var result = false; + if (!(value && typeof value == 'object') || isArguments(value)) { + return result; + } + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings. + // Also check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) && + (!isFunction(ctor) || ctor instanceof ctor)) { + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + if (iteratesOwnLast) { + forIn(value, function(value, key, object) { + result = !hasOwnProperty.call(object, key); + return false; + }); + return result === false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + forIn(value, function(value, key) { + result = key; + }); + return result === false || hasOwnProperty.call(value, result); + } + return result; + } + + /** + * A fallback implementation of `Object.keys` that produces an array of the + * given object's own enumerable property names. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + */ + function shimKeys(object) { + var result = []; + forOwn(object, function(value, key) { + result.push(key); + }); + return result; + } + + /** + * Used to convert characters to HTML entities: + * + * Though the `>` character is escaped for symmetry, characters like `>` and `/` + * don't require escaping in HTML and have no special meaning unless they're part + * of a tag or an unquoted attribute value. + * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to convert HTML entities to characters */ + var htmlUnescapes = invert(htmlEscapes); + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a clone of `value`. If `deep` is `true`, all nested objects will + * also be cloned otherwise they will be assigned by reference. Functions, DOM + * nodes, `arguments` objects, and objects created by constructors other than + * `Object` are **not** cloned. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to clone. + * @param {Boolean} deep A flag to indicate a deep clone. + * @param- {Object} [guard] Internally used to allow this method to work with + * others like `_.map` without using their callback `index` argument for `deep`. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate clones with their + * source counterparts. + * @returns {Mixed} Returns the cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 }, + * { 'name': 'curly', 'age': 60 } + * ]; + * + * _.clone({ 'name': 'moe' }); + * // => { 'name': 'moe' } + * + * var shallow = _.clone(stooges); + * shallow[0] === stooges[0]; + * // => true + * + * var deep = _.clone(stooges, true); + * shallow[0] === stooges[0]; + * // => false + */ + function clone(value, deep, guard, stackA, stackB) { + if (value == null) { + return value; + } + if (guard) { + deep = false; + } + // inspect [[Class]] + var isObj = isObject(value); + if (isObj) { + // don't clone `arguments` objects, functions, or non-object Objects + var className = toString.call(value); + if (!cloneableClasses[className] || (noArgsClass && isArguments(value))) { + return value; + } + var isArr = className == arrayClass; + isObj = isArr || (className == objectClass ? isPlainObject(value) : isObj); + } + // shallow clone + if (!isObj || !deep) { + // don't clone functions + return isObj + ? (isArr ? slice.call(value) : extend({}, value)) + : value; + } + + var ctor = value.constructor; + switch (className) { + case boolClass: + case dateClass: + return new ctor(+value); + + case numberClass: + case stringClass: + return new ctor(value); + + case regexpClass: + return ctor(value.source, reFlags.exec(value)); + } + // check for circular references and return corresponding clone + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // init cloned object + var result = isArr ? ctor(value.length) : {}; + + // add the source value to the stack of traversed objects + // and associate it with its clone + stackA.push(value); + stackB.push(result); + + // recursively populate clone (susceptible to call stack limits) + (isArr ? forEach : forOwn)(value, function(objValue, key) { + result[key] = clone(objValue, deep, null, stackA, stackB); + }); + + return result; + } + + /** + * Assigns enumerable properties of the default object(s) to the `destination` + * object for all `destination` properties that resolve to `null`/`undefined`. + * Once a property is set, additional defaults of the same property will be + * ignored. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [default1, default2, ...] The default objects. + * @returns {Object} Returns the destination object. + * @example + * + * var iceCream = { 'flavor': 'chocolate' }; + * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' }); + * // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' } + */ + var defaults = createIterator(extendIteratorOptions, { + 'objectLoop': 'if (result[index] == null) ' + extendIteratorOptions.objectLoop + }); + + /** + * Assigns enumerable properties of the source object(s) to the `destination` + * object. Subsequent sources will overwrite propery assignments of previous + * sources. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @returns {Object} Returns the destination object. + * @example + * + * _.extend({ 'name': 'moe' }, { 'age': 40 }); + * // => { 'name': 'moe', 'age': 40 } + */ + var extend = createIterator(extendIteratorOptions); + + /** + * Creates a sorted array of all enumerable properties, own and inherited, + * of `object` that have function values. + * + * @static + * @memberOf _ + * @alias methods + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names that have function values. + * @example + * + * _.functions(_); + * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + */ + function functions(object) { + var result = []; + forIn(object, function(value, key) { + if (isFunction(value)) { + result.push(key); + } + }); + return result.sort(); + } + + /** + * Checks if the specified object `property` exists and is a direct property, + * instead of an inherited property. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to check. + * @param {String} property The property to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + * @example + * + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); + * // => true + */ + function has(object, property) { + return object ? hasOwnProperty.call(object, property) : false; + } + + /** + * Creates an object composed of the inverted keys and values of the given `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to invert. + * @returns {Object} Returns the created inverted object. + * @example + * + * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' }); + * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed) + */ + function invert(object) { + var result = {}; + forOwn(object, function(value, key) { + result[value] = key; + }); + return result; + } + + /** + * Checks if `value` is an array. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is an array, else `false`. + * @example + * + * (function() { return _.isArray(arguments); })(); + * // => false + * + * _.isArray([1, 2, 3]); + * // => true + */ + var isArray = nativeIsArray || function(value) { + return toString.call(value) == arrayClass; + }; + + /** + * Checks if `value` is a boolean (`true` or `false`) value. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`. + * @example + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || toString.call(value) == boolClass; + } + + /** + * Checks if `value` is a date. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a date, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + */ + function isDate(value) { + return toString.call(value) == dateClass; + } + + /** + * Checks if `value` is a DOM element. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + */ + function isElement(value) { + return value ? value.nodeType === 1 : false; + } + + /** + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object|String} value The value to inspect. + * @returns {Boolean} Returns `true` if the `value` is empty, else `false`. + * @example + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({}); + * // => true + * + * _.isEmpty(''); + * // => true + */ + function isEmpty(value) { + var result = true; + if (!value) { + return result; + } + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + className == argsClass || (noArgsClass && isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + return !length; + } + forOwn(value, function() { + return (result = false); + }); + return result; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent to each other. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} a The value to compare. + * @param {Mixed} b The other value to compare. + * @param- {Object} [stackA=[]] Internally used track traversed `a` objects. + * @param- {Object} [stackB=[]] Internally used track traversed `b` objects. + * @returns {Boolean} Returns `true` if the values are equvalent, else `false`. + * @example + * + * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] }; + * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] }; + * + * moe == clone; + * // => false + * + * _.isEqual(moe, clone); + * // => true + */ + function isEqual(a, b, stackA, stackB) { + // exit early for identical values + if (a === b) { + // treat `+0` vs. `-0` as not equal + return a !== 0 || (1 / a == 1 / b); + } + // a strict comparison is necessary because `null == undefined` + if (a == null || b == null) { + return a === b; + } + // compare [[Class]] names + var className = toString.call(a); + if (className != toString.call(b)) { + return false; + } + switch (className) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal + return +a == +b; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return a != +a + ? b != +b + // but treat `+0` vs. `-0` as not equal + : (a == 0 ? (1 / a == 1 / b) : a == +b); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.com/#x15.10.6.4) + // treat string primitives and their corresponding object instances as equal + return a == b + ''; + } + // exit early, in older browsers, if `a` is array-like but not `b` + var isArr = className == arrayClass || className == argsClass; + if (noArgsClass && !isArr && (isArr = isArguments(a)) && !isArguments(b)) { + return false; + } + if (!isArr) { + // unwrap any `lodash` wrapped values + if (a.__wrapped__ || b.__wrapped__) { + return isEqual(a.__wrapped__ || a, b.__wrapped__ || b); + } + // exit for functions and DOM nodes + if (className != objectClass || (noNodeClass && ( + (typeof a.toString != 'function' && typeof (a + '') == 'string') || + (typeof b.toString != 'function' && typeof (b + '') == 'string')))) { + return false; + } + var ctorA = a.constructor, + ctorB = b.constructor; + + // non `Object` object instances with different constructors are not equal + if (ctorA != ctorB && !( + isFunction(ctorA) && ctorA instanceof ctorA && + isFunction(ctorB) && ctorB instanceof ctorB + )) { + return false; + } + } + // assume cyclic structures are equal + // the algorithm for detecting cyclic structures is adapted from ES 5.1 + // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3) + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == a) { + return stackB[length] == b; + } + } + + var index = -1, + result = true, + size = 0; + + // add `a` and `b` to the stack of traversed objects + stackA.push(a); + stackB.push(b); + + // recursively compare objects and arrays (susceptible to call stack limits) + if (isArr) { + // compare lengths to determine if a deep comparison is necessary + size = a.length; + result = size == b.length; + + if (result) { + // deep compare the contents, ignoring non-numeric properties + while (size--) { + if (!(result = isEqual(a[size], b[size], stackA, stackB))) { + break; + } + } + } + return result; + } + // deep compare objects + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // count the number of properties. + size++; + // deep compare each property value. + if (!(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) { + return false; + } + } + } + // ensure both objects have the same number of properties + for (key in b) { + // The JS engine in Adobe products, like InDesign, has a bug that causes + // `!size--` to throw an error so it must be wrapped in parentheses. + // https://github.com/documentcloud/underscore/issues/355 + if (hasOwnProperty.call(b, key) && !(size--)) { + // `size` will be `-1` if `b` has more properties than `a` + return false; + } + } + // handle JScript [[DontEnum]] bug + if (hasDontEnumBug) { + while (++index < 7) { + key = shadowed[index]; + if (hasOwnProperty.call(a, key) && + !(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) { + return false; + } + } + } + return true; + } + + /** + * Checks if `value` is, or can be coerced to, a finite number. + * + * Note: This is not the same as native `isFinite`, which will return true for + * booleans and empty strings. See http://es5.github.com/#x15.1.2.5. + * + * @deprecated + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`. + * @example + * + * _.isFinite(-101); + * // => true + * + * _.isFinite('10'); + * // => true + * + * _.isFinite(true); + * // => false + * + * _.isFinite(''); + * // => false + * + * _.isFinite(Infinity); + * // => false + */ + function isFinite(value) { + return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + } + + /** + * Checks if `value` is a function. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + */ + function isFunction(value) { + return typeof value == 'function'; + } + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return toString.call(value) == funcClass; + }; + } + + /** + * Checks if `value` is the language type of Object. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ + function isObject(value) { + // check if the value is the ECMAScript language type of Object + // http://es5.github.com/#x8 + // and avoid a V8 bug + // http://code.google.com/p/v8/issues/detail?id=2291 + return value ? objectTypes[typeof value] : false; + } + + /** + * Checks if `value` is `NaN`. + * + * Note: This is not the same as native `isNaN`, which will return true for + * `undefined` and other values. See http://es5.github.com/#x15.1.2.4. + * + * @deprecated + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // `NaN` as a primitive is the only value that is not equal to itself + // (perform the [[Class]] check first to avoid errors with some host objects in IE) + return toString.call(value) == numberClass && value != +value + } + + /** + * Checks if `value` is `null`. + * + * @deprecated + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(undefined); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is a number. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a number, else `false`. + * @example + * + * _.isNumber(8.4 * 5); + * // => true + */ + function isNumber(value) { + return toString.call(value) == numberClass; + } + + /** + * Checks if a given `value` is an object created by the `Object` constructor. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Stooge(name, age) { + * this.name = name; + * this.age = age; + * } + * + * _.isPlainObject(new Stooge('moe', 40)); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'name': 'moe', 'age': 40 }); + * // => true + */ + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && typeof value == 'object')) { + return false; + } + var valueOf = value.valueOf, + objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value)) + : shimIsPlainObject(value); + }; + + /** + * Checks if `value` is a regular expression. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`. + * @example + * + * _.isRegExp(/moe/); + * // => true + */ + function isRegExp(value) { + return toString.call(value) == regexpClass; + } + + /** + * Checks if `value` is a string. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a string, else `false`. + * @example + * + * _.isString('moe'); + * // => true + */ + function isString(value) { + return toString.call(value) == stringClass; + } + + /** + * Checks if `value` is `undefined`. + * + * @deprecated + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Creates an array composed of the own enumerable property names of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + * @example + * + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (order is not guaranteed) + */ + var keys = !nativeKeys ? shimKeys : function(object) { + // avoid iterating over the `prototype` property + return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype') + ? shimKeys(object) + : (isObject(object) ? nativeKeys(object) : []); + }; + + /** + * Merges enumerable properties of the source object(s) into the `destination` + * object. Subsequent sources will overwrite propery assignments of previous + * sources. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param- {Object} [indicator] Internally used to indicate that the `stack` + * argument is an array of traversed objects instead of another source object. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate values with their + * source counterparts. + * @returns {Object} Returns the destination object. + * @example + * + * var stooges = [ + * { 'name': 'moe' }, + * { 'name': 'larry' } + * ]; + * + * var ages = [ + * { 'age': 40 }, + * { 'age': 50 } + * ]; + * + * _.merge(stooges, ages); + * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] + */ + function merge(object, source, indicator) { + var args = arguments, + index = 0, + length = 2, + stackA = args[3], + stackB = args[4]; + + if (indicator !== objectRef) { + stackA = []; + stackB = []; + length = args.length; + } + while (++index < length) { + forOwn(args[index], function(source, key) { + var found, isArr, value; + if (source && ((isArr = isArray(source)) || isPlainObject(source))) { + // avoid merging previously merged cyclic sources + var stackLength = stackA.length; + while (stackLength--) { + found = stackA[stackLength] == source; + if (found) { + break; + } + } + if (found) { + object[key] = stackB[stackLength]; + } + else { + // add `source` and associated `value` to the stack of traversed objects + stackA.push(source); + stackB.push(value = (value = object[key], isArr) + ? (isArray(value) ? value : []) + : (isPlainObject(value) ? value : {}) + ); + // recursively merge objects and arrays (susceptible to call stack limits) + object[key] = merge(value, source, objectRef, stackA, stackB); + } + } else if (source != null) { + object[key] = source; + } + }); + } + return object; + } + + /** + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If `callback` is passed, it will be executed for each property + * in the `object`, omitting the properties `callback` returns truthy for. The + * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit + * or the function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. + * @example + * + * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid'); + * // => { 'name': 'moe', 'age': 40 } + * + * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) { + * return key.charAt(0) == '_'; + * }); + * // => { 'name': 'moe' } + */ + function omit(object, callback, thisArg) { + var isFunc = typeof callback == 'function', + result = {}; + + if (isFunc) { + callback = createCallback(callback, thisArg); + } else { + var props = concat.apply(arrayRef, arguments); + } + forIn(object, function(value, key, object) { + if (isFunc + ? !callback(value, key, object) + : indexOf(props, key, 1) < 0 + ) { + result[key] = value; + } + }); + return result; + } + + /** + * Creates a two dimensional array of the given object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. + * @example + * + * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 }); + * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed) + */ + function pairs(object) { + var result = []; + forOwn(object, function(value, key) { + result.push([key, value]); + }); + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If `callback` is passed, it will be executed for each property + * in the `object`, picking the properties `callback` returns truthy for. The + * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick + * or the function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age'); + * // => { 'name': 'moe', 'age': 40 } + * + * _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'moe' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = 0, + props = concat.apply(arrayRef, arguments), + length = props.length; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = createCallback(callback, thisArg); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * Creates an array composed of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property values. + * @example + * + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] + */ + function values(object) { + var result = []; + forOwn(object, function(value) { + result.push(value); + }); + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Checks if a given `target` element is present in a `collection` using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @alias include + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Mixed} target The value to check for. + * @param {Number} [fromIndex=0] The index to search from. + * @returns {Boolean} Returns `true` if the `target` element is found, else `false`. + * @example + * + * _.contains([1, 2, 3], 1); + * // => true + * + * _.contains([1, 2, 3], 1, 2); + * // => false + * + * _.contains({ 'name': 'moe', 'age': 40 }, 'moe'); + * // => true + * + * _.contains('curly', 'ur'); + * // => true + */ + function contains(collection, target, fromIndex) { + var index = -1, + length = collection ? collection.length : 0; + + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; + if (typeof length == 'number') { + return (isString(collection) + ? collection.indexOf(target, fromIndex) + : indexOf(collection, target, fromIndex) + ) > -1; + } + return some(collection, function(value) { + return ++index >= fromIndex && value === target; + }); + } + + /** + * Creates an object composed of keys returned from running each element of + * `collection` through a `callback`. The corresponding value of each key is + * the number of times the key was returned by `callback`. The `callback` is + * bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * The `callback` argument may also be the name of a property to count by (e.g. 'length'). + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} callback|property The function called per iteration + * or property name to count by. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': 1, '6': 2 } + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + function countBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection); + (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); + }); + return result; + } + + /** + * Checks if the `callback` returns a truthy value for **all** elements of a + * `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * @static + * @memberOf _ + * @alias all + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if all elements pass the callback check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + */ + function every(collection, callback, thisArg) { + var result = true; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (!(result = !!callback(collection[index], index, collection))) { + break; + } + } + } else { + forEach(collection, function(value, index, collection) { + return (result = !!callback(value, index, collection)); + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * the `callback` returns truthy for. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * @static + * @memberOf _ + * @alias select + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that passed the callback check. + * @example + * + * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [2, 4, 6] + */ + function filter(collection, callback, thisArg) { + var result = []; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * Examines each element in a `collection`, returning the first one the `callback` + * returns truthy for. The function returns as soon as it finds an acceptable + * element, and does not iterate over the entire `collection`. The `callback` is + * bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * @static + * @memberOf _ + * @alias detect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the element that passed the callback check, + * else `undefined`. + * @example + * + * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => 2 + */ + function find(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; + } + + /** + * Iterates over a `collection`, executing the `callback` for each element in + * the `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). Callbacks may exit iteration early + * by explicitly returning `false`. + * + * @static + * @memberOf _ + * @alias each + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + * @example + * + * _([1, 2, 3]).forEach(alert).join(','); + * // => alerts each number and returns '1,2,3' + * + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert); + * // => alerts each number (order is not guaranteed) + */ + var forEach = createIterator(forEachIteratorOptions); + + /** + * Creates an object composed of keys returned from running each element of + * `collection` through a `callback`. The corresponding value of each key is an + * array of elements passed to `callback` that returned the key. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * The `callback` argument may also be the name of a property to group by (e.g. 'length'). + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} callback|property The function called per iteration + * or property name to group by. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + function groupBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection); + (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); + }); + return result; + } + + /** + * Invokes the method named by `methodName` on each element in the `collection`, + * returning an array of the results of each invoked method. Additional arguments + * will be passed to each invoked method. If `methodName` is a function it will + * be invoked for, and `this` bound to, each element in the `collection`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} Returns a new array of the results of each invoked method. + * @example + * + * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invoke([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + function invoke(collection, methodName) { + var args = slice.call(arguments, 2), + isFunc = typeof methodName == 'function', + result = []; + + forEach(collection, function(value) { + result.push((isFunc ? methodName : value[methodName]).apply(value, args)); + }); + return result; + } + + /** + * Creates an array of values by running each element in the `collection` + * through a `callback`. The `callback` is bound to `thisArg` and invoked with + * three arguments; (value, index|key, collection). + * + * @static + * @memberOf _ + * @alias collect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of the results of each `callback` execution. + * @example + * + * _.map([1, 2, 3], function(num) { return num * 3; }); + * // => [3, 6, 9] + * + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * // => [3, 6, 9] (order is not guaranteed) + */ + function map(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + if (isArray(collection)) { + while (++index < length) { + result[index] = callback(collection[index], index, collection); + } + } else { + forEach(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); + } + return result; + } + + /** + * Retrieves the maximum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index, collection). + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the maximum value. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 }, + * { 'name': 'curly', 'age': 60 } + * ]; + * + * _.max(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'curly', 'age': 60 }; + */ + function max(collection, callback, thisArg) { + var computed = -Infinity, + index = -1, + length = collection ? collection.length : 0, + result = computed; + + if (callback || !isArray(collection)) { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + forEach(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current > computed) { + computed = current; + result = value; + } + }); + } else { + while (++index < length) { + if (collection[index] > result) { + result = collection[index]; + } + } + } + return result; + } + + /** + * Retrieves the minimum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, collection). + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the minimum value. + * @example + * + * _.min([10, 5, 100, 2, 1000]); + * // => 2 + */ + function min(collection, callback, thisArg) { + var computed = Infinity, + index = -1, + length = collection ? collection.length : 0, + result = computed; + + if (callback || !isArray(collection)) { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + forEach(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current < computed) { + computed = current; + result = value; + } + }); + } else { + while (++index < length) { + if (collection[index] < result) { + result = collection[index]; + } + } + } + return result; + } + + /** + * Retrieves the value of a specified property from all elements in + * the `collection`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {String} property The property to pluck. + * @returns {Array} Returns a new array of property values. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 }, + * { 'name': 'curly', 'age': 60 } + * ]; + * + * _.pluck(stooges, 'name'); + * // => ['moe', 'larry', 'curly'] + */ + function pluck(collection, property) { + var result = []; + forEach(collection, function(value) { + result.push(value[property]); + }); + return result; + } + + /** + * Boils down a `collection` to a single value. The initial state of the + * reduction is `accumulator` and each successive step of it should be returned + * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4 + * arguments; for arrays they are (accumulator, value, index|key, collection). + * + * @static + * @memberOf _ + * @alias foldl, inject + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; }); + * // => 6 + */ + function reduce(collection, callback, accumulator, thisArg) { + var noaccum = arguments.length < 3; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, index, collection) { + accumulator = noaccum + ? (noaccum = false, value) + : callback(accumulator, value, index, collection) + }); + return accumulator; + } + + /** + * The right-associative version of `_.reduce`. + * + * @static + * @memberOf _ + * @alias foldr + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var list = [[0, 1], [2, 3], [4, 5]]; + * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, callback, accumulator, thisArg) { + var iteratee = collection, + length = collection ? collection.length : 0, + noaccum = arguments.length < 3; + + if (typeof length != 'number') { + var props = keys(collection); + length = props.length; + } else if (noCharByIndex && isString(collection)) { + iteratee = collection.split(''); + } + forEach(collection, function(value, index, collection) { + index = props ? props[--length] : --length; + accumulator = noaccum + ? (noaccum = false, iteratee[index]) + : callback.call(thisArg, accumulator, iteratee[index], index, collection); + }); + return accumulator; + } + + /** + * The opposite of `_.filter`, this method returns the values of a + * `collection` that `callback` does **not** return truthy for. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that did **not** pass the + * callback check. + * @example + * + * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [1, 3, 5] + */ + function reject(collection, callback, thisArg) { + callback = createCallback(callback, thisArg); + return filter(collection, function(value, index, collection) { + return !callback(value, index, collection); + }); + } + + /** + * Creates an array of shuffled `array` values, using a version of the + * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to shuffle. + * @returns {Array} Returns a new shuffled collection. + * @example + * + * _.shuffle([1, 2, 3, 4, 5, 6]); + * // => [4, 1, 6, 3, 5, 2] + */ + function shuffle(collection) { + var index = -1, + result = Array(collection ? collection.length : 0); + + forEach(collection, function(value) { + var rand = floor(nativeRandom() * (++index + 1)); + result[index] = result[rand]; + result[rand] = value; + }); + return result; + } + + /** + * Gets the size of the `collection` by returning `collection.length` for arrays + * and array-like objects or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to inspect. + * @returns {Number} Returns `collection.length` or number of own enumerable properties. + * @example + * + * _.size([1, 2]); + * // => 2 + * + * _.size({ 'one': 1, 'two': 2, 'three': 3 }); + * // => 3 + * + * _.size('curly'); + * // => 5 + */ + function size(collection) { + var length = collection ? collection.length : 0; + return typeof length == 'number' ? length : keys(collection).length; + } + + /** + * Checks if the `callback` returns a truthy value for **any** element of a + * `collection`. The function returns as soon as it finds passing value, and + * does not iterate over the entire `collection`. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * @static + * @memberOf _ + * @alias any + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if any element passes the callback check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false]); + * // => true + */ + function some(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (result = callback(collection[index], index, collection)) { + break; + } + } + } else { + forEach(collection, function(value, index, collection) { + return !(result = callback(value, index, collection)); + }); + } + return !!result; + } + + /** + * Creates an array, stable sorted in ascending order by the results of + * running each element of `collection` through a `callback`. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * The `callback` argument may also be the name of a property to sort by (e.g. 'length'). + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} callback|property The function called per iteration + * or property name to sort by. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of sorted elements. + * @example + * + * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * // => [3, 1, 2] + * + * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * // => [3, 1, 2] + * + * _.sortBy(['larry', 'brendan', 'moe'], 'length'); + * // => ['moe', 'larry', 'brendan'] + */ + function sortBy(collection, callback, thisArg) { + var result = []; + callback = createCallback(callback, thisArg); + forEach(collection, function(value, index, collection) { + result.push({ + 'criteria': callback(value, index, collection), + 'index': index, + 'value': value + }); + }); + + var length = result.length; + result.sort(compareAscending); + while (length--) { + result[length] = result[length].value; + } + return result; + } + + /** + * Converts the `collection`, to an array. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to convert. + * @returns {Array} Returns the new converted array. + * @example + * + * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); + * // => [2, 3, 4] + */ + function toArray(collection) { + if (collection && typeof collection.length == 'number') { + return (noArraySliceOnStrings ? isString(collection) : typeof collection == 'string') + ? collection.split('') + : slice.call(collection); + } + return values(collection); + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * that contain the given `properties`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Object} properties The object of property values to filter by. + * @returns {Array} Returns a new array of elements that contain the given `properties`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 }, + * { 'name': 'curly', 'age': 60 } + * ]; + * + * _.where(stooges, { 'age': 40 }); + * // => [{ 'name': 'moe', 'age': 40 }] + */ + function where(collection, properties) { + var props = []; + forIn(properties, function(value, prop) { + props.push(prop); + }); + return filter(collection, function(object) { + var length = props.length; + while (length--) { + var result = object[props[length]] === properties[props[length]]; + if (!result) { + break; + } + } + return !!result; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values of `array` removed. The values + * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result.push(value); + } + } + return result; + } + + /** + * Creates an array of `array` elements not present in the other arrays + * using strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {Array} [array1, array2, ...] Arrays to check. + * @returns {Array} Returns a new array of `array` elements not present in the + * other arrays. + * @example + * + * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); + * // => [1, 3, 4] + */ + function difference(array) { + var index = -1, + length = array ? array.length : 0, + flattened = concat.apply(arrayRef, arguments), + contains = cachedContains(flattened, length), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Gets the first element of the `array`. Pass `n` to return the first `n` + * elements of the `array`. + * + * @static + * @memberOf _ + * @alias head, take + * @category Arrays + * @param {Array} array The array to query. + * @param {Number} [n] The number of elements to return. + * @param- {Object} [guard] Internally used to allow this method to work with + * others like `_.map` without using their callback `index` argument for `n`. + * @returns {Mixed} Returns the first element or an array of the first `n` + * elements of `array`. + * @example + * + * _.first([5, 4, 3, 2, 1]); + * // => 5 + */ + function first(array, n, guard) { + if (array) { + return (n == null || guard) ? array[0] : slice.call(array, 0, n); + } + } + + /** + * Flattens a nested array (the nesting can be to any depth). If `shallow` is + * truthy, `array` will only be flattened a single level. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @param {Boolean} shallow A flag to indicate only flattening a single level. + * @returns {Array} Returns a new flattened array. + * @example + * + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; + * + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, [[4]]]; + */ + function flatten(array, shallow) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + + // recursively flatten arrays (susceptible to call stack limits) + if (isArray(value)) { + push.apply(result, shallow ? value : flatten(value)); + } else { + result.push(value); + } + } + return result; + } + + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If the `array` is already + * sorted, passing `true` for `fromIndex` will run a faster binary search. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to + * perform a binary search on a sorted `array`. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 + * + * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); + * // => 2 + */ + function indexOf(array, value, fromIndex) { + var index = -1, + length = array ? array.length : 0; + + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1; + } else if (fromIndex) { + index = sortedIndex(array, value); + return array[index] === value ? index : -1; + } + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Gets all but the last element of `array`. Pass `n` to exclude the last `n` + * elements from the result. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Number} [n=1] The number of elements to exclude. + * @param- {Object} [guard] Internally used to allow this method to work with + * others like `_.map` without using their callback `index` argument for `n`. + * @returns {Array} Returns all but the last element or `n` elements of `array`. + * @example + * + * _.initial([3, 2, 1]); + * // => [3, 2] + */ + function initial(array, n, guard) { + return array + ? slice.call(array, 0, -((n == null || guard) ? 1 : n)) + : []; + } + + /** + * Computes the intersection of all the passed-in arrays using strict equality + * for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique elements, in order, that are + * present in **all** of the arrays. + * @example + * + * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2] + */ + function intersection(array) { + var args = arguments, + argsLength = args.length, + cache = {}, + result = []; + + forEach(array, function(value) { + if (indexOf(result, value) < 0) { + var length = argsLength; + while (--length) { + if (!(cache[length] || (cache[length] = cachedContains(args[length])))(value)) { + return; + } + } + result.push(value); + } + }); + return result; + } + + /** + * Gets the last element of the `array`. Pass `n` to return the last `n` + * elements of the `array`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Number} [n] The number of elements to return. + * @param- {Object} [guard] Internally used to allow this method to work with + * others like `_.map` without using their callback `index` argument for `n`. + * @returns {Mixed} Returns the last element or an array of the last `n` + * elements of `array`. + * @example + * + * _.last([3, 2, 1]); + * // => 1 + */ + function last(array, n, guard) { + if (array) { + var length = array.length; + return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length); + } + } + + /** + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=array.length-1] The index to search from. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var index = array ? array.length : 0; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Creates an object composed from arrays of `keys` and `values`. Pass either + * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or + * two arrays, one of `keys` and one of corresponding `values`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} keys The array of keys. + * @param {Array} [values=[]] The array of values. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. + * @example + * + * _.object(['moe', 'larry', 'curly'], [30, 40, 50]); + * // => { 'moe': 30, 'larry': 40, 'curly': 50 } + */ + function object(keys, values) { + var index = -1, + length = keys ? keys.length : 0, + result = {}; + + while (++index < length) { + var key = keys[index]; + if (values) { + result[key] = values[index]; + } else { + result[key[0]] = key[1]; + } + } + return result; + } + + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `stop`. This method is a port of Python's + * `range()` function. See http://docs.python.org/library/functions.html#range. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Number} [start=0] The start of the range. + * @param {Number} end The end of the range. + * @param {Number} [step=1] The value to increment or descrement by. + * @returns {Array} Returns a new range array. + * @example + * + * _.range(10); + * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * + * _.range(1, 11); + * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + * + * _.range(0, 30, 5); + * // => [0, 5, 10, 15, 20, 25] + * + * _.range(0, -10, -1); + * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = +step || 1; + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so V8 will avoid the slower "dictionary" mode + // http://www.youtube.com/watch?v=XAqIpGU8ZZk#t=16m27s + var index = -1, + length = nativeMax(0, ceil((end - start) / step)), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * The opposite of `_.initial`, this method gets all but the first value of + * `array`. Pass `n` to exclude the first `n` values from the result. + * + * @static + * @memberOf _ + * @alias drop, tail + * @category Arrays + * @param {Array} array The array to query. + * @param {Number} [n=1] The number of elements to exclude. + * @param- {Object} [guard] Internally used to allow this method to work with + * others like `_.map` without using their callback `index` argument for `n`. + * @returns {Array} Returns all but the first value or `n` values of `array`. + * @example + * + * _.rest([3, 2, 1]); + * // => [2, 1] + */ + function rest(array, n, guard) { + return array + ? slice.call(array, (n == null || guard) ? 1 : n) + : []; + } + + /** + * Uses a binary search to determine the smallest index at which the `value` + * should be inserted into `array` in order to maintain the sort order of the + * sorted `array`. If `callback` is passed, it will be executed for `value` and + * each element in `array` to compute their sort ranking. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). The `callback` + * argument may also be the name of a property to order by. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to iterate over. + * @param {Mixed} value The value to evaluate. + * @param {Function|String} [callback=identity|property] The function called + * per iteration or property name to order by. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Number} Returns the index at which the value should be inserted + * into `array`. + * @example + * + * _.sortedIndex([20, 30, 50], 40); + * // => 2 + * + * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 2 + * + * var dict = { + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * }; + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return dict.wordToNumber[word]; + * }); + * // => 2 + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return this.wordToNumber[word]; + * }, dict); + * // => 2 + */ + function sortedIndex(array, value, callback, thisArg) { + var low = 0, + high = array ? array.length : low; + + // explicitly reference `identity` for better engine inlining + callback = callback ? createCallback(callback, thisArg) : identity; + value = callback(value); + while (low < high) { + var mid = (low + high) >>> 1; + callback(array[mid]) < value + ? low = mid + 1 + : high = mid; + } + return low; + } + + /** + * Computes the union of the passed-in arrays using strict equality for + * comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique values, in order, that are + * present in one or more of the arrays. + * @example + * + * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2, 3, 101, 10] + */ + function union() { + return uniq(concat.apply(arrayRef, arguments)); + } + + /** + * Creates a duplicate-value-free version of the `array` using strict equality + * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` + * for `isSorted` will run a faster algorithm. If `callback` is passed, each + * element of `array` is passed through a callback` before uniqueness is computed. + * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * @static + * @memberOf _ + * @alias unique + * @category Arrays + * @param {Array} array The array to process. + * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a duplicate-value-free array. + * @example + * + * _.uniq([1, 2, 1, 3, 1]); + * // => [1, 2, 3] + * + * _.uniq([1, 1, 2, 2, 3], true); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); }); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math); + * // => [1, 2, 3] + */ + function uniq(array, isSorted, callback, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = [], + seen = result; + + // juggle arguments + if (typeof isSorted == 'function') { + thisArg = callback; + callback = isSorted; + isSorted = false; + } + // init value cache for large arrays + var isLarge = !isSorted && length > 74; + if (isLarge) { + var cache = {}; + } + if (callback) { + seen = []; + callback = createCallback(callback, thisArg); + } + while (++index < length) { + var value = array[index], + computed = callback ? callback(value, index, array) : value; + + if (isLarge) { + // manually coerce `computed` to a string because `hasOwnProperty`, in + // some older versions of Firefox, coerces objects incorrectly + seen = hasOwnProperty.call(cache, computed + '') ? cache[computed] : (cache[computed] = []); + } + if (isSorted + ? !index || seen[seen.length - 1] !== computed + : indexOf(seen, computed) < 0 + ) { + if (callback || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * Creates an array with all occurrences of the passed values removed using + * strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to filter. + * @param {Mixed} [value1, value2, ...] Values to remove. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] + */ + function without(array) { + var index = -1, + length = array ? array.length : 0, + contains = cachedContains(arguments, 1, 20), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Groups the elements of each array at their corresponding indexes. Useful for + * separate data sources that are coordinated through matching array indexes. + * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix + * in a similar fashion. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of grouped elements. + * @example + * + * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]); + * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]] + */ + function zip(array) { + var index = -1, + length = array ? max(pluck(arguments, 'length')) : 0, + result = Array(length); + + while (++index < length) { + result[index] = pluck(arguments, index); + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function that is restricted to executing `func` only after it is + * called `n` times. The `func` is executed with the `this` binding of the + * created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Number} n The number of times the function must be called before + * it is executed. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var renderNotes = _.after(notes.length, render); + * _.forEach(notes, function(note) { + * note.asyncSave({ 'success': renderNotes }); + * }); + * // `renderNotes` is run once, after all notes have saved + */ + function after(n, func) { + if (n < 1) { + return func(); + } + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * passed to the bound function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to bind. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var func = function(greeting) { + * return greeting + ' ' + this.name; + * }; + * + * func = _.bind(func, { 'name': 'moe' }, 'hi'); + * func(); + * // => 'hi moe' + */ + function bind(func, thisArg) { + // use `Function#bind` if it exists and is fast + // (in V8 `Function#bind` is slower except when partially applied) + return isBindFast || (nativeBind && arguments.length > 2) + ? nativeBind.call.apply(nativeBind, arguments) + : createBound(func, thisArg, slice.call(arguments, 2)); + } + + /** + * Binds methods on `object` to `object`, overwriting the existing method. + * If no method names are provided, all the function properties of `object` + * will be bound. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object to bind and assign the bound methods to. + * @param {String} [methodName1, methodName2, ...] Method names on the object to bind. + * @returns {Object} Returns `object`. + * @example + * + * var buttonView = { + * 'label': 'lodash', + * 'onClick': function() { alert('clicked: ' + this.label); } + * }; + * + * _.bindAll(buttonView); + * jQuery('#lodash_button').on('click', buttonView.onClick); + * // => When the button is clicked, `this.label` will have the correct value + */ + function bindAll(object) { + var funcs = arguments, + index = funcs.length > 1 ? 0 : (funcs = functions(object), -1), + length = funcs.length; + + while (++index < length) { + var key = funcs[index]; + object[key] = bind(object[key], object); + } + return object; + } + + /** + * Creates a function that is the composition of the passed functions, + * where each function consumes the return value of the function that follows. + * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * Each function is executed with the `this` binding of the composed function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} [func1, func2, ...] Functions to compose. + * @returns {Function} Returns the new composed function. + * @example + * + * var greet = function(name) { return 'hi: ' + name; }; + * var exclaim = function(statement) { return statement + '!'; }; + * var welcome = _.compose(exclaim, greet); + * welcome('moe'); + * // => 'hi: moe!' + */ + function compose() { + var funcs = arguments; + return function() { + var args = arguments, + length = funcs.length; + + while (length--) { + args = [funcs[length].apply(this, args)]; + } + return args[0]; + }; + } + + /** + * Creates a function that will delay the execution of `func` until after + * `wait` milliseconds have elapsed since the last time it was invoked. Pass + * `true` for `immediate` to cause debounce to invoke `func` on the leading, + * instead of the trailing, edge of the `wait` timeout. Subsequent calls to + * the debounced function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to debounce. + * @param {Number} wait The number of milliseconds to delay. + * @param {Boolean} immediate A flag to indicate execution is on the leading + * edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * var lazyLayout = _.debounce(calculateLayout, 300); + * jQuery(window).on('resize', lazyLayout); + */ + function debounce(func, wait, immediate) { + var args, + result, + thisArg, + timeoutId; + + function delayed() { + timeoutId = null; + if (!immediate) { + result = func.apply(thisArg, args); + } + } + return function() { + var isImmediate = immediate && !timeoutId; + args = arguments; + thisArg = this; + + clearTimeout(timeoutId); + timeoutId = setTimeout(delayed, wait); + + if (isImmediate) { + result = func.apply(thisArg, args); + } + return result; + }; + } + + /** + * Executes the `func` function after `wait` milliseconds. Additional arguments + * will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to delay. + * @param {Number} wait The number of milliseconds to delay execution. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * var log = _.bind(console.log, console); + * _.delay(log, 1000, 'logged later'); + * // => 'logged later' (Appears after one second.) + */ + function delay(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * Defers executing the `func` function until the current call stack has cleared. + * Additional arguments will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to defer. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * _.defer(function() { alert('deferred'); }); + * // returns from the function before `alert` is called + */ + function defer(func) { + var args = slice.call(arguments, 1); + return setTimeout(function() { func.apply(undefined, args); }, 1); + } + + /** + * Creates a function that, when called, invokes `object[methodName]` and + * prepends any additional `lateBind` arguments to those passed to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object the method belongs to. + * @param {String} methodName The method name. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'name': 'moe', + * 'greet': function(greeting) { + * return greeting + ' ' + this.name; + * } + * }; + * + * var func = _.lateBind(object, 'greet', 'hi'); + * func(); + * // => 'hi moe' + * + * object.greet = function(greeting) { + * return greeting + ', ' + this.name + '!'; + * }; + * + * func(); + * // => 'hi, moe!' + */ + function lateBind(object, methodName) { + return createBound(methodName, object, slice.call(arguments, 2)); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * passed, it will be used to determine the cache key for storing the result + * based on the arguments passed to the memoized function. By default, the first + * argument passed to the memoized function is used as the cache key. The `func` + * is executed with the `this` binding of the memoized function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] A function used to resolve the cache key. + * @returns {Function} Returns the new memoizing function. + * @example + * + * var fibonacci = _.memoize(function(n) { + * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * }); + */ + function memoize(func, resolver) { + var cache = {}; + return function() { + var key = resolver ? resolver.apply(this, arguments) : arguments[0]; + return hasOwnProperty.call(cache, key) + ? cache[key] + : (cache[key] = func.apply(this, arguments)); + }; + } + + /** + * Creates a function that is restricted to execute `func` once. Repeat calls to + * the function will return the value of the first call. The `func` is executed + * with the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // Application is only created once. + */ + function once(func) { + var result, + ran = false; + + return function() { + if (ran) { + return result; + } + ran = true; + result = func.apply(this, arguments); + + // clear the `func` variable so the function may be garbage collected + func = null; + return result; + }; + } + + /** + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those passed to the new function. This + * method is similar to `bind`, except it does **not** alter the `this` binding. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var greet = function(greeting, name) { return greeting + ': ' + name; }; + * var hi = _.partial(greet, 'hi'); + * hi('moe'); + * // => 'hi: moe' + */ + function partial(func) { + return createBound(func, slice.call(arguments, 1)); + } + + /** + * Creates a function that, when executed, will only call the `func` + * function at most once per every `wait` milliseconds. If the throttled + * function is invoked more than once during the `wait` timeout, `func` will + * also be called on the trailing edge of the timeout. Subsequent calls to the + * throttled function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to throttle. + * @param {Number} wait The number of milliseconds to throttle executions to. + * @returns {Function} Returns the new throttled function. + * @example + * + * var throttled = _.throttle(updatePosition, 100); + * jQuery(window).on('scroll', throttled); + */ + function throttle(func, wait) { + var args, + result, + thisArg, + timeoutId, + lastCalled = 0; + + function trailingCall() { + lastCalled = new Date; + timeoutId = null; + result = func.apply(thisArg, args); + } + return function() { + var now = new Date, + remaining = wait - (now - lastCalled); + + args = arguments; + thisArg = this; + + if (remaining <= 0) { + clearTimeout(timeoutId); + lastCalled = now; + result = func.apply(thisArg, args); + } + else if (!timeoutId) { + timeoutId = setTimeout(trailingCall, remaining); + } + return result; + }; + } + + /** + * Creates a function that passes `value` to the `wrapper` function as its + * first argument. Additional arguments passed to the function are appended + * to those passed to the `wrapper` function. The `wrapper` is executed with + * the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Mixed} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var hello = function(name) { return 'hello ' + name; }; + * hello = _.wrap(hello, function(func) { + * return 'before, ' + func('moe') + ', after'; + * }); + * hello(); + * // => 'before, hello moe, after' + */ + function wrap(value, wrapper) { + return function() { + var args = [value]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their + * corresponding HTML entities. + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} string The string to escape. + * @returns {String} Returns the escaped string. + * @example + * + * _.escape('Moe, Larry & Curly'); + * // => "Moe, Larry & Curly" + */ + function escape(string) { + return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * This function returns the first argument passed to it. + * + * Note: It is used throughout Lo-Dash as a default callback. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Mixed} value Any value. + * @returns {Mixed} Returns `value`. + * @example + * + * var moe = { 'name': 'moe' }; + * moe === _.identity(moe); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Adds functions properties of `object` to the `lodash` function and chainable + * wrapper. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object of function properties to add to `lodash`. + * @example + * + * _.mixin({ + * 'capitalize': function(string) { + * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + * } + * }); + * + * _.capitalize('larry'); + * // => 'Larry' + * + * _('curly').capitalize(); + * // => 'Curly' + */ + function mixin(object) { + forEach(functions(object), function(methodName) { + var func = lodash[methodName] = object[methodName]; + + lodash.prototype[methodName] = function() { + var args = [this.__wrapped__]; + push.apply(args, arguments); + + var result = func.apply(lodash, args); + if (this.__chain__) { + result = new lodash(result); + result.__chain__ = true; + } + return result; + }; + }); + } + + /** + * Reverts the '_' variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Utilities + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + window._ = oldDash; + return this; + } + + /** + * Produces a random number between `min` and `max` (inclusive). If only one + * argument is passed, a number between `0` and the given number will be returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Number} [min=0] The minimum possible value. + * @param {Number} [max=1] The maximum possible value. + * @returns {Number} Returns a random number. + * @example + * + * _.random(0, 5); + * // => a number between 1 and 5 + * + * _.random(5); + * // => also a number between 1 and 5 + */ + function random(min, max) { + if (min == null && max == null) { + max = 1; + } + min = +min || 0; + if (max == null) { + max = min; + min = 0; + } + return min + floor(nativeRandom() * ((+max || 0) - min + 1)); + } + + /** + * Resolves the value of `property` on `object`. If `property` is a function + * it will be invoked and its result returned, else the property value is + * returned. If `object` is falsey, then `null` is returned. + * + * @deprecated + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object to inspect. + * @param {String} property The property to get the value of. + * @returns {Mixed} Returns the resolved value. + * @example + * + * var object = { + * 'cheese': 'crumpets', + * 'stuff': function() { + * return 'nonsense'; + * } + * }; + * + * _.result(object, 'cheese'); + * // => 'crumpets' + * + * _.result(object, 'stuff'); + * // => 'nonsense' + */ + function result(object, property) { + // based on Backbone's private `getValue` function + // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424 + var value = object ? object[property] : null; + return isFunction(value) ? object[property]() : value; + } + + /** + * A micro-templating method that handles arbitrary delimiters, preserves + * whitespace, and correctly escapes quotes within interpolated code. + * + * Note: In the development build `_.template` utilizes sourceURLs for easier + * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl + * + * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` + * build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page. + * See http://developer.chrome.com/trunk/extensions/sandboxingEval.html + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} text The template text. + * @param {Obect} data The data object used to populate the text. + * @param {Object} options The options object. + * escape - The "escape" delimiter regexp. + * evaluate - The "evaluate" delimiter regexp. + * interpolate - The "interpolate" delimiter regexp. + * sourceURL - The sourceURL of the template's compiled source. + * variable - The data object variable name. + * + * @returns {Function|String} Returns a compiled function when no `data` object + * is given, else it returns the interpolated text. + * @example + * + * // using a compiled template + * var compiled = _.template('hello <%= name %>'); + * compiled({ 'name': 'moe' }); + * // => 'hello moe' + * + * var list = '<% _.forEach(people, function(name) { %>
        1. <%= name %>
        2. <% }); %>'; + * _.template(list, { 'people': ['moe', 'larry', 'curly'] }); + * // => '
        3. moe
        4. larry
        5. curly
        6. ' + * + * // using the "escape" delimiter to escape HTML in data property values + * _.template('<%- value %>', { 'value': '\n```\n\nUsing [npm](http://npmjs.org/):\n\n```bash\nnpm install lodash\n\nnpm install -g lodash\nnpm link lodash\n```\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n```\n\n**Note:** If Lo-Dash is installed globally, [run `npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it.\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n```js\nvar _ = require('lodash')._;\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire({\n 'paths': {\n 'underscore': 'path/to/lodash'\n }\n},\n['underscore'], function(_) {\n console.log(_.VERSION);\n});\n```\n\n## Resolved Underscore.js issues\n\n * Allow iteration of objects with a `length` property [[#799](https://github.com/documentcloud/underscore/pull/799), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L545-551)]\n * Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L558-582)]\n * Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L140-146)]\n * `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L747-752)]\n * `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L828-840)]\n * `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L921-923)]\n * `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/lodash/lodash/blob/0.9.2/test/test.js#L1337-1340)]\n\n## Release Notes\n\n### v0.9.2\n\n * Added `fromIndex` argument to `_.contains`\n * Added `moduleId` build option\n * Added Closure Compiler *“simple”* optimizations to the build process\n * Added support for strings in `_.max` and `_.min`\n * Added support for ES6 template delimiters to `_.template`\n * Ensured re-minification of Lo-Dash by third parties avoids Closure Compiler bugs\n * Optimized `_.every`, `_.find`, `_.some`, and `_.uniq`\n\nThe full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog).\n\n## BestieJS\n\nLo-Dash is part of the [BestieJS](https://github.com/bestiejs) *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.\n\n## Author\n\n| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton \"Follow @jdalton on Twitter\") |\n|---|\n| [John-David Dalton](http://allyoucanleet.com/) |\n\n## Contributors\n\n| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](http://twitter.com/blainebublitz \"Follow @BlaineBublitz on Twitter\") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias \"Follow @mathias on Twitter\") |\n|---|---|---|\n| [Blaine Bublitz](http://iceddev.com/) | [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) |\n", + "readmeFilename": "README.md", + "_id": "lodash@0.9.2", + "dist": { + "shasum": "fcd4d3c508f2497bf819857d9fd76fca075818c2" + }, + "_from": "lodash@~0.9.0", + "_resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz" +} diff --git a/node_modules/grunt/node_modules/minimatch/LICENSE b/node_modules/grunt/node_modules/minimatch/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/minimatch/README.md b/node_modules/grunt/node_modules/minimatch/README.md new file mode 100644 index 000000000..6fd07d2e9 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/README.md @@ -0,0 +1,218 @@ +# minimatch + +A minimal matching utility. + +[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch) + + +This is the matching library used internally by npm. + +Eventually, it will replace the C binding in node-glob. + +It works by converting glob expressions into JavaScript `RegExp` +objects. + +## Usage + +```javascript +var minimatch = require("minimatch") + +minimatch("bar.foo", "*.foo") // true! +minimatch("bar.foo", "*.bar") // false! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +### Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between minimatch and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. **Note that this is different from the way that `**` is +handled by ruby's `Dir` class.** + +If an escaped pattern has no matches, and the `nonull` flag is set, +then minimatch.match returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + + +## Minimatch Class + +Create a minimatch object by instanting the `minimatch.Minimatch` class. + +```javascript +var Minimatch = require("minimatch").Minimatch +var mm = new Minimatch(pattern, options) +``` + +### Properties + +* `pattern` The original pattern the minimatch object represents. +* `options` The options supplied to the constructor. +* `set` A 2-dimensional array of regexp or string expressions. + Each row in the + array corresponds to a brace-expanded pattern. Each item in the row + corresponds to a single path-part. For example, the pattern + `{a,b/c}/d` would expand to a set of patterns like: + + [ [ a, d ] + , [ b, c, d ] ] + + If a portion of the pattern doesn't have any "magic" in it + (that is, it's something like `"foo"` rather than `fo*o?`), then it + will be left as a string rather than converted to a regular + expression. + +* `regexp` Created by the `makeRe` method. A single regular expression + expressing the entire pattern. This is useful in cases where you wish + to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. +* `negate` True if the pattern is negated. +* `comment` True if the pattern is a comment. +* `empty` True if the pattern is `""`. + +### Methods + +* `makeRe` Generate the `regexp` member if necessary, and return it. + Will return `false` if the pattern is invalid. +* `match(fname)` Return true if the filename matches the pattern, or + false otherwise. +* `matchOne(fileArray, patternArray, partial)` Take a `/`-split + filename, and match it against a single row in the `regExpSet`. This + method is mainly for internal use, but is exposed so that it can be + used by a glob-walker that needs to avoid excessive filesystem calls. + +All other methods are internal, and will be called as necessary. + +## Functions + +The top-level exported function has a `cache` property, which is an LRU +cache set to store 100 items. So, calling these methods repeatedly +with the same pattern and options will use the same Minimatch object, +saving the cost of parsing it multiple times. + +### minimatch(path, pattern, options) + +Main export. Tests a path against the pattern using the options. + +```javascript +var isJS = minimatch(file, "*.js", { matchBase: true }) +``` + +### minimatch.filter(pattern, options) + +Returns a function that tests its +supplied argument, suitable for use with `Array.filter`. Example: + +```javascript +var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) +``` + +### minimatch.match(list, pattern, options) + +Match against the list of +files, in the style of fnmatch or glob. If nothing is matched, and +options.nonull is set, then return a list containing the pattern itself. + +```javascript +var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) +``` + +### minimatch.makeRe(pattern, options) + +Make a regular expression object from the pattern. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### nobrace + +Do not expand `{a,b}` and `{1..3}` brace sets. + +### noglobstar + +Disable `**` matching against multiple folder names. + +### dot + +Allow patterns to match filenames starting with a period, even if +the pattern does not explicitly have a period in that spot. + +Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` +is set. + +### noext + +Disable "extglob" style patterns like `+(a|b)`. + +### nocase + +Perform a case-insensitive match. + +### nonull + +When a match is not found by `minimatch.match`, return a list containing +the pattern itself. When set, an empty list is returned if there are +no matches. + +### matchBase + +If set, then patterns without slashes will be matched +against the basename of the path if it contains slashes. For example, +`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + +### nocomment + +Suppress the behavior of treating `#` at the start of a pattern as a +comment. + +### nonegate + +Suppress the behavior of treating a leading `!` character as negation. + +### flipNegate + +Returns from negate expressions the same as if they were not negated. +(Ie, true on a hit, false on a miss.) diff --git a/node_modules/grunt/node_modules/minimatch/minimatch.js b/node_modules/grunt/node_modules/minimatch/minimatch.js new file mode 100644 index 000000000..405746b67 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/minimatch.js @@ -0,0 +1,1079 @@ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.monkeyPatch = monkeyPatch +function monkeyPatch () { + var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") + var orig = desc.value + desc.value = function (p) { + if (p instanceof Minimatch) return p.match(this) + return orig.call(this, p) + } + Object.defineProperty(String.prototype, desc) +} + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) console.error(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + if (options.debug) console.error(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + if (options.debug) console.error(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + if (options.debug) console.error(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + // console.error(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + // console.error("no sets") + return [pattern] + } + + var tail = braceExpand(pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + // console.error("numset", numset[1], numset[2]) + var suf = braceExpand(pattern.substr(numset[0].length), options) + , start = +numset[1] + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + for (var i = start; i != (end + inc); i += inc) { + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(i + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + // console.error("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + // console.error("didn't close", pattern) + return braceExpand("\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + // console.error("set", set) + // console.error("suffix", pattern.substr(i)) + var suf = braceExpand(pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + // console.error("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand(p, options) + }) + // console.error("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + if (options.debug) { + console.error("%s\t%s %s %j", pattern, i, re, c) + } + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + if (options.debug) { + console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + } + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + // console.error("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + // console.error("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + if (options.debug) { + console.error(this.pattern, "split", f) + } + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + // console.error(this.pattern, "set", set) + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i] + var hit = this.matchOne(f, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + if (options.debug) { + console.error("matchOne", + { "this": this + , file: file + , pattern: pattern }) + } + + if (options.matchBase && pattern.length === 1) { + file = path.basename(file.join("/")).split("/") + } + + if (options.debug) { + console.error("matchOne", file.length, pattern.length) + } + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + if (options.debug) { + console.error("matchOne loop") + } + var p = pattern[pi] + , f = file[fi] + + if (options.debug) { + console.error(pattern, p, f) + } + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + if (options.debug) + console.error('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + if (options.debug) + console.error('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + if (options.debug) { + console.error('\nglobstar while', + file, fr, pattern, pr, swallowee) + } + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + if (options.debug) + console.error('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + if (options.debug) + console.error("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + if (options.debug) + console.error('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + // console.error("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + if (options.debug) { + console.error("string match", p, f, hit) + } + } else { + hit = f.match(p) + if (options.debug) { + console.error("pattern match", p, f, hit) + } + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 000000000..07e6e472c --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/AUTHORS b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/AUTHORS new file mode 100644 index 000000000..016d7fbe1 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 000000000..03ee0f985 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,97 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/bench.js b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/bench.js new file mode 100644 index 000000000..91115400b --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/bench.js @@ -0,0 +1,25 @@ +var LRU = require('lru-cache'); + +var max = +process.argv[2] || 10240; +var more = 102400; + +var cache = LRU({ + max: max, maxAge: 86400e3 +}); + +// fill cache +for (var i = 0; i < max; ++i) { + cache.set(i, {}); +} + +var start = process.hrtime(); + +// adding more items +for ( ; i < max+more; ++i) { + cache.set(i, {}); +} + +var end = process.hrtime(start); +var msecs = end[0] * 1E3 + end[1] / 1E6; + +console.log('adding %d items took %d ms', more, msecs.toPrecision(5)); diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 000000000..49c1dc6de --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,263 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) { + return new LRUCache(options) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + + if (!options) options = {} + + max = options.max + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var allowStale = options.stale || false + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , lru = 0 // least recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + i++ + var hit = lruList[k] + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } + } + + this.keys = function () { + var keys = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + keys[i++] = hit.key + } + return keys + } + + this.values = function () { + var values = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + values[i++] = hit.value + } + return values + } + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.dumpLru = function () { + return lruList + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.has = function (key) { + if (!hOP(cache, key)) return false + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + return false + } + return true + } + + this.get = function (key) { + return get(key, true) + } + + this.peek = function (key) { + return get(key, false) + } + + function get (key, doUse) { + var hit = cache[key] + if (hit) { + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } else { + if (doUse) use(hit) + } + if (hit) hit = hit.value + } + return hit + } + + function use (hit) { + shiftLU(hit) + hit.lu = mru ++ + lruList[hit.lu] = hit + } + + this.del = function (key) { + del(cache[key]) + } + + function trim () { + while (lru < mru && length > max) + del(lruList[lru]) + } + + function shiftLU(hit) { + delete lruList[ hit.lu ] + while (lru < mru && !lruList[lru]) lru ++ + } + + function del(hit) { + if (hit) { + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + itemCount -- + delete cache[ hit.key ] + shiftLU(hit) + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 000000000..411acad3b --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,62 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.3.1", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `peek(key)`\n\n Returns the key value (or `undefined` if not found) without\n updating the \"recently used\"-ness of the key.\n\n (If you find yourself using this a lot, you *might* be using the\n wrong sort of data structure, but there are some use cases where\n it's handy.)\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "_id": "lru-cache@2.3.1", + "_from": "lru-cache@2" +} diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 000000000..70f3f8beb --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,329 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/foreach.js new file mode 100644 index 000000000..eefb80d9d --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 000000000..7af45b022 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 000000000..0c44ae716 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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. diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 000000000..7e365129e --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/README.md @@ -0,0 +1,53 @@ +# sigmund + +Quick and dirty signatures for Objects. + +This is like a much faster `deepEquals` comparison, which returns a +string key suitable for caches and the like. + +## Usage + +```javascript +function doSomething (someObj) { + var key = sigmund(someObj, maxDepth) // max depth defaults to 10 + var cached = cache.get(key) + if (cached) return cached) + + var result = expensiveCalculation(someObj) + cache.set(key, result) + return result +} +``` + +The resulting key will be as unique and reproducible as calling +`JSON.stringify` or `util.inspect` on the object, but is much faster. +In order to achieve this speed, some differences are glossed over. +For example, the object `{0:'foo'}` will be treated identically to the +array `['foo']`. + +Also, just as there is no way to summon the soul from the scribblings +of a cocain-addled psychoanalyst, there is no way to revive the object +from the signature string that sigmund gives you. In fact, it's +barely even readable. + +As with `sys.inspect` and `JSON.stringify`, larger objects will +produce larger signature strings. + +Because sigmund is a bit less strict than the more thorough +alternatives, the strings will be shorter, and also there is a +slightly higher chance for collisions. For example, these objects +have the same signature: + + var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} + var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +Like a good Freudian, sigmund is most effective when you already have +some understanding of what you're looking for. It can help you help +yourself, but you must be willing to do some work as well. + +Cycles are handled, and cyclical objects are silently omitted (though +the key is included in the signature output.) + +The second argument is the maximum depth, which defaults to 10, +because that is the maximum object traversal depth covered by most +insurance carriers. diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 000000000..5acfd6d90 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/bench.js @@ -0,0 +1,283 @@ +// different ways to id objects +// use a req/res pair, since it's crazy deep and cyclical + +// sparseFE10 and sigmund are usually pretty close, which is to be expected, +// since they are essentially the same algorithm, except that sigmund handles +// regular expression objects properly. + + +var http = require('http') +var util = require('util') +var sigmund = require('./sigmund.js') +var sreq, sres, creq, cres, test + +http.createServer(function (q, s) { + sreq = q + sres = s + sres.end('ok') + this.close(function () { setTimeout(function () { + start() + }, 200) }) +}).listen(1337, function () { + creq = http.get({ port: 1337 }) + creq.on('response', function (s) { cres = s }) +}) + +function start () { + test = [sreq, sres, creq, cres] + // test = sreq + // sreq.sres = sres + // sreq.creq = creq + // sreq.cres = cres + + for (var i in exports.compare) { + console.log(i) + var hash = exports.compare[i]() + console.log(hash) + console.log(hash.length) + console.log('') + } + + require('bench').runMain() +} + +function customWs (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '') + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return customWs(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + customWs(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function custom (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return '' + obj + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return custom(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + custom(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function sparseFE2 (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ':' + ch(v[k], depth + 1) + }) + soFar += '}' + } + ch(obj, 0) + return soFar +} + +function sparseFE (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ch(v[k], depth + 1) + }) + } + ch(obj, 0) + return soFar +} + +function sparse (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ch(v[k], depth + 1) + } + } + ch(obj, 0) + return soFar +} + +function noCommas (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + + +function flatten (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + soFar += ',' + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + +exports.compare = +{ + // 'custom 2': function () { + // return custom(test, 2, 0) + // }, + // 'customWs 2': function () { + // return customWs(test, 2, 0) + // }, + 'JSON.stringify (guarded)': function () { + var seen = [] + return JSON.stringify(test, function (k, v) { + if (typeof v !== 'object' || !v) return v + if (seen.indexOf(v) !== -1) return undefined + seen.push(v) + return v + }) + }, + + 'flatten 10': function () { + return flatten(test, 10) + }, + + // 'flattenFE 10': function () { + // return flattenFE(test, 10) + // }, + + 'noCommas 10': function () { + return noCommas(test, 10) + }, + + 'sparse 10': function () { + return sparse(test, 10) + }, + + 'sparseFE 10': function () { + return sparseFE(test, 10) + }, + + 'sparseFE2 10': function () { + return sparseFE2(test, 10) + }, + + sigmund: function() { + return sigmund(test, 10) + }, + + + // 'util.inspect 1': function () { + // return util.inspect(test, false, 1, false) + // }, + // 'util.inspect undefined': function () { + // util.inspect(test) + // }, + // 'util.inspect 2': function () { + // util.inspect(test, false, 2, false) + // }, + // 'util.inspect 3': function () { + // util.inspect(test, false, 3, false) + // }, + // 'util.inspect 4': function () { + // util.inspect(test, false, 4, false) + // }, + // 'util.inspect Infinity': function () { + // util.inspect(test, false, Infinity, false) + // } +} + +/** results +**/ diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 000000000..ec8e2eb3e --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,41 @@ +{ + "name": "sigmund", + "version": "1.0.0", + "description": "Quick and dirty signatures for Objects.", + "main": "sigmund.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.0" + }, + "scripts": { + "test": "tap test/*.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/sigmund" + }, + "keywords": [ + "object", + "signature", + "key", + "data", + "psychoanalysis" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "BSD", + "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/sigmund/issues" + }, + "_id": "sigmund@1.0.0", + "_from": "sigmund@~1.0.0" +} diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 000000000..82c7ab8ce --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -0,0 +1,39 @@ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: diff --git a/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 000000000..50c53a13e --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -0,0 +1,24 @@ +var test = require('tap').test +var sigmund = require('../sigmund.js') + + +// occasionally there are duplicates +// that's an acceptable edge-case. JSON.stringify and util.inspect +// have some collision potential as well, though less, and collision +// detection is expensive. +var hash = '{abc/def/g{0h1i2{jkl' +var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} +var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +var obj3 = JSON.parse(JSON.stringify(obj1)) +obj3.c = /def/ +obj3.g[2].cycle = obj3 +var cycleHash = '{abc/def/g{0h1i2{jklcycle' + +test('basic', function (t) { + t.equal(sigmund(obj1), hash) + t.equal(sigmund(obj2), hash) + t.equal(sigmund(obj3), cycleHash) + t.end() +}) + diff --git a/node_modules/grunt/node_modules/minimatch/package.json b/node_modules/grunt/node_modules/minimatch/package.json new file mode 100644 index 000000000..d5a1fd001 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.2.12", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE" + }, + "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n### Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n Each row in the\n array corresponds to a brace-expanded pattern. Each item in the row\n corresponds to a single path-part. For example, the pattern\n `{a,b/c}/d` would expand to a set of patterns like:\n\n [ [ a, d ]\n , [ b, c, d ] ]\n\n If a portion of the pattern doesn't have any \"magic\" in it\n (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n will be left as a string rather than converted to a regular\n expression.\n\n* `regexp` Created by the `makeRe` method. A single regular expression\n expressing the entire pattern. This is useful in cases where you wish\n to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n filename, and match it against a single row in the `regExpSet`. This\n method is mainly for internal use, but is exposed so that it can be\n used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items. So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`. Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob. If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself. When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes. For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/minimatch/issues" + }, + "_id": "minimatch@0.2.12", + "_from": "minimatch@0.x.x" +} diff --git a/node_modules/grunt/node_modules/minimatch/test/basic.js b/node_modules/grunt/node_modules/minimatch/test/basic.js new file mode 100644 index 000000000..ae7ac73c7 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/test/basic.js @@ -0,0 +1,399 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + + +var patterns = + [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + // https://github.com/isaacs/minimatch/issues/5 + , function () { + files = [ 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' + , 'a/b/.x' + , 'a/b/.x/' + , 'a/.x/b' + , '.x' + , '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b/.x/c' + , '.x/.x' ] + } + , ["**/.x/**", [ '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b' + , 'a/b/.x/' + , 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' ] ] + + ] + +var regexps = + [ '/^(?:(?=.)a[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:\\*)$/', + '/^(?:(?=.)\\*[^/]*?)$/', + '/^(?:\\*\\*)$/', + '/^(?:(?=.)b[^/]*?\\/)$/', + '/^(?:(?=.)c[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/', + '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/', + '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/', + '/^(?:(?=.)a[^/]*?[^c])$/', + '/^(?:(?=.)a[X-]b)$/', + '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/', + '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[^/]c)$/', + '/^(?:a\\*c)$/', + 'false', + '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/', + '/^(?:man\\/man1\\/bash\\.1)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[-abc])$/', + '/^(?:(?!\\.)(?=.)[abc-])$/', + '/^(?:\\\\)$/', + '/^(?:(?!\\.)(?=.)[\\\\])$/', + '/^(?:(?!\\.)(?=.)[\\[])$/', + '/^(?:\\[)$/', + '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[\\]])$/', + '/^(?:(?!\\.)(?=.)[\\]-])$/', + '/^(?:(?!\\.)(?=.)[a-z])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:\\[\\])$/', + '/^(?:\\[abc)$/', + '/^(?:(?=.)XYZ)$/i', + '/^(?:(?=.)ab[^/]*?)$/i', + '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i', + '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/', + '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/', + '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/', + '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/', + '/^(?:(?=.)a[^/]b)$/', + '/^(?:(?=.)#[^/]*?)$/', + '/^(?!^(?:(?=.)a[^/]*?)$).*$/', + '/^(?:(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)a[^/]*?)$/', + '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ] +var re = 0; + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + patterns.forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var m = new mm.Minimatch(pattern, options) + var r = m.makeRe() + var expectRe = regexps[re++] + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + + t.equal(tapOpts.re, expectRe, tapOpts) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt/node_modules/minimatch/test/brace-expand.js b/node_modules/grunt/node_modules/minimatch/test/brace-expand.js new file mode 100644 index 000000000..7ee278a27 --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/grunt/node_modules/minimatch/test/caching.js b/node_modules/grunt/node_modules/minimatch/test/caching.js new file mode 100644 index 000000000..0fec4b0fa --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/grunt/node_modules/minimatch/test/defaults.js b/node_modules/grunt/node_modules/minimatch/test/defaults.js new file mode 100644 index 000000000..25f1f601c --- /dev/null +++ b/node_modules/grunt/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt/node_modules/nopt/.npmignore b/node_modules/grunt/node_modules/nopt/.npmignore new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/nopt/LICENSE b/node_modules/grunt/node_modules/nopt/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/nopt/README.md b/node_modules/grunt/node_modules/nopt/README.md new file mode 100644 index 000000000..eeddfd4fe --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/README.md @@ -0,0 +1,208 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/grunt/node_modules/nopt/bin/nopt.js b/node_modules/grunt/node_modules/nopt/bin/nopt.js new file mode 100755 index 000000000..df90c729a --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/grunt/node_modules/nopt/examples/my-program.js b/node_modules/grunt/node_modules/nopt/examples/my-program.js new file mode 100755 index 000000000..142447e18 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/grunt/node_modules/nopt/lib/nopt.js b/node_modules/grunt/node_modules/nopt/lib/nopt.js new file mode 100644 index 000000000..ff802dafe --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/lib/nopt.js @@ -0,0 +1,552 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + data.argv.toString = function () { + return this.original.map(JSON.stringify).join(" ") + } + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = false + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = no || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know the-rules --and so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate 2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} diff --git a/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/nopt/node_modules/abbrev/README.md b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 000000000..99746fe67 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js new file mode 100644 index 000000000..bee4132c9 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,111 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") +var util = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} diff --git a/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json new file mode 100644 index 000000000..55ed011bf --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,28 @@ +{ + "name": "abbrev", + "version": "1.0.4", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/abbrev-js/issues" + }, + "_id": "abbrev@1.0.4", + "_from": "abbrev@1" +} diff --git a/node_modules/grunt/node_modules/nopt/package.json b/node_modules/grunt/node_modules/nopt/package.json new file mode 100644 index 000000000..35c8f64c1 --- /dev/null +++ b/node_modules/grunt/node_modules/nopt/package.json @@ -0,0 +1,35 @@ +{ + "name": "nopt", + "version": "1.0.10", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/nopt/issues" + }, + "_id": "nopt@1.0.10", + "_from": "nopt@~1.0.10" +} diff --git a/node_modules/grunt/node_modules/rimraf/AUTHORS b/node_modules/grunt/node_modules/rimraf/AUTHORS new file mode 100644 index 000000000..247b75437 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/AUTHORS @@ -0,0 +1,6 @@ +# Authors sorted by whether or not they're me. +Isaac Z. Schlueter (http://blog.izs.me) +Wayne Larsen (http://github.com/wvl) +ritch +Marcel Laverdet +Yosef Dinerstein diff --git a/node_modules/grunt/node_modules/rimraf/LICENSE b/node_modules/grunt/node_modules/rimraf/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/rimraf/README.md b/node_modules/grunt/node_modules/rimraf/README.md new file mode 100644 index 000000000..96ce9b2a0 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/README.md @@ -0,0 +1,21 @@ +A `rm -rf` for node. + +Install with `npm install rimraf`, or just drop rimraf.js somewhere. + +## API + +`rimraf(f, callback)` + +The callback will be called with an error if there is one. Certain +errors are handled for you: + +* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times + before giving up. +* `EMFILE` - If too many file descriptors get opened, rimraf will + patiently wait until more become available. + + +## rimraf.sync + +It can remove stuff synchronously, too. But that's not so good. Use +the async API. It's better. diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/.npmignore b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/.npmignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/LICENSE b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/LICENSE new file mode 100644 index 000000000..05a401094 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/README.md b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/README.md new file mode 100644 index 000000000..7d2e681e3 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/README.md @@ -0,0 +1,5 @@ +Just like node's `fs` module, but it does an incremental back-off when +EMFILE is encountered. + +Useful in asynchronous situations where one needs to try to open lots +and lots of files. diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js new file mode 100644 index 000000000..be9951eac --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js @@ -0,0 +1,312 @@ +// this keeps a queue of opened file descriptors, and will make +// fs operations wait until some have closed before trying to open more. + +var fs = require("fs") + +// there is such a thing as TOO graceful. +if (fs.open === gracefulOpen) return + +var queue = [] + , constants = require("constants") + +exports = module.exports = fs +fs._curOpen = 0 + +fs.MIN_MAX_OPEN = 64 +fs.MAX_OPEN = 1024 + +var originalOpen = fs.open + , originalOpenSync = fs.openSync + , originalClose = fs.close + , originalCloseSync = fs.closeSync + + +// prevent EMFILE errors +function OpenReq (path, flags, mode, cb) { + this.path = path + this.flags = flags + this.mode = mode + this.cb = cb +} + +function noop () {} + +fs.open = gracefulOpen + +function gracefulOpen (path, flags, mode, cb) { + if (typeof mode === "function") cb = mode, mode = null + if (typeof cb !== "function") cb = noop + + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new OpenReq(path, flags, mode, cb)) + setTimeout(flush) + return + } + open(path, flags, mode, function (er, fd) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + // that was too many. reduce max, get back in queue. + // this should only happen once in a great while, and only + // if the ulimit -n is set lower than 1024. + fs.MAX_OPEN = fs._curOpen - 1 + return fs.open(path, flags, mode, cb) + } + cb(er, fd) + }) +} + +function open (path, flags, mode, cb) { + cb = cb || noop + fs._curOpen ++ + originalOpen.call(fs, path, flags, mode, function (er, fd) { + if (er) onclose() + cb(er, fd) + }) +} + +fs.openSync = function (path, flags, mode) { + var ret + ret = originalOpenSync.call(fs, path, flags, mode) + fs._curOpen ++ + return ret +} + +function onclose () { + fs._curOpen -- + flush() +} + +function flush () { + while (fs._curOpen < fs.MAX_OPEN) { + var req = queue.shift() + if (!req) return + open(req.path, req.flags || "r", req.mode || 0777, req.cb) + } +} + +fs.close = function (fd, cb) { + cb = cb || noop + originalClose.call(fs, fd, function (er) { + onclose() + cb(er) + }) +} + +fs.closeSync = function (fd) { + onclose() + return originalCloseSync.call(fs, fd) +} + + +// (re-)implement some things that are known busted or missing. + +var constants = require("constants") + +// lchmod, broken prior to 0.6.2 +// back-port the fix here. +if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + fs.lchmod = function (path, mode, callback) { + callback = callback || noop + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var err, err2 + try { + var ret = fs.fchmodSync(fd, mode) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } +} + + +// lutimes implementation, or no-op +if (!fs.lutimes) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + cb = cb || noop + if (er) return cb(er) + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + return cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + , err + , err2 + , ret + + try { + var ret = fs.futimesSync(fd, at, mt) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } + + } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) { + // maybe utimensat will be bound soonish? + fs.lutimes = function (path, at, mt, cb) { + fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb) + } + + fs.lutimesSync = function (path, at, mt) { + return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW) + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) } + fs.lutimesSync = function () {} + } +} + + +// https://github.com/isaacs/node-graceful-fs/issues/4 +// Chown should not fail on einval or eperm if non-root. + +fs.chown = chownFix(fs.chown) +fs.fchown = chownFix(fs.fchown) +fs.lchown = chownFix(fs.lchown) + +fs.chownSync = chownFixSync(fs.chownSync) +fs.fchownSync = chownFixSync(fs.fchownSync) +fs.lchownSync = chownFixSync(fs.lchownSync) + +function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er, res) { + if (chownErOk(er)) er = null + cb(er, res) + }) + } +} + +function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + +function chownErOk (er) { + // if there's no getuid, or if getuid() is something other than 0, + // and the error is EINVAL or EPERM, then just ignore it. + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // When running as root, or if other types of errors are encountered, + // then it's strict. + if (!er || (!process.getuid || process.getuid() !== 0) + && (er.code === "EINVAL" || er.code === "EPERM")) return true +} + + +// if lchmod/lchown do not exist, then make them no-ops +if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + process.nextTick(cb) + } + fs.lchmodSync = function () {} +} +if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + process.nextTick(cb) + } + fs.lchownSync = function () {} +} + + + +// on Windows, A/V software can lock the directory, causing this +// to fail with an EACCES or EPERM if the directory contains newly +// created files. Try again on failure, for up to 1 second. +if (process.platform === "win32") { + var rename_ = fs.rename + fs.rename = function rename (from, to, cb) { + var start = Date.now() + rename_(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 1000) { + return rename_(from, to, CB) + } + cb(er) + }) + } +} + + +// if read() returns EAGAIN, then just try it again. +var read = fs.read +fs.read = function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return read.call(fs, fd, buffer, offset, length, position, callback) +} + +var readSync = fs.readSync +fs.readSync = function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } +} diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/package.json b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/package.json new file mode 100644 index 000000000..013cd7d81 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/package.json @@ -0,0 +1,43 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "graceful-fs", + "description": "fs monkey-patching to avoid EMFILE and other problems", + "version": "1.1.14", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-graceful-fs.git" + }, + "main": "graceful-fs.js", + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "keywords": [ + "fs", + "EMFILE", + "error", + "handling", + "monkeypatch" + ], + "license": "BSD", + "readme": "Just like node's `fs` module, but it does an incremental back-off when\nEMFILE is encountered.\n\nUseful in asynchronous situations where one needs to try to open lots\nand lots of files.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-graceful-fs/issues" + }, + "_id": "graceful-fs@1.1.14", + "dist": { + "shasum": "5f784ede0567383c85a4d3c3120a2131db9e6e53" + }, + "_from": "graceful-fs@~1.1", + "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz" +} diff --git a/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/test/open.js b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/test/open.js new file mode 100644 index 000000000..d05f880c8 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs/test/open.js @@ -0,0 +1,41 @@ +var test = require('tap').test +var fs = require('../graceful-fs.js') + +test('open an existing file works', function (t) { + var start = fs._curOpen + var fd = fs.openSync(__filename, 'r') + t.equal(fs._curOpen, start + 1) + fs.closeSync(fd) + t.equal(fs._curOpen, start) + fs.open(__filename, 'r', function (er, fd) { + if (er) throw er + t.equal(fs._curOpen, start + 1) + fs.close(fd, function (er) { + if (er) throw er + t.equal(fs._curOpen, start) + t.end() + }) + }) +}) + +test('open a non-existing file throws', function (t) { + var start = fs._curOpen + var er + try { + var fd = fs.openSync('this file does not exist', 'r') + } catch (x) { + er = x + } + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + t.equal(fs._curOpen, start) + + fs.open('neither does this file', 'r', function (er, fd) { + t.ok(er, 'should throw') + t.notOk(fd, 'should not get an fd') + t.equal(er.code, 'ENOENT') + t.equal(fs._curOpen, start) + t.end() + }) +}) diff --git a/node_modules/grunt/node_modules/rimraf/package.json b/node_modules/grunt/node_modules/rimraf/package.json new file mode 100644 index 000000000..4ad7399e1 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/package.json @@ -0,0 +1,62 @@ +{ + "name": "rimraf", + "version": "2.0.3", + "main": "rimraf.js", + "description": "A deep deletion module for node (like `rm -rf`)", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/rimraf/raw/master/LICENSE" + }, + "optionalDependencies": { + "graceful-fs": "~1.1" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/rimraf.git" + }, + "scripts": { + "test": "cd test && bash run.sh" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + { + "name": "Wayne Larsen", + "email": "wayne@larsen.st", + "url": "http://github.com/wvl" + }, + { + "name": "ritch", + "email": "skawful@gmail.com" + }, + { + "name": "Marcel Laverdet" + }, + { + "name": "Yosef Dinerstein", + "email": "yosefd@microsoft.com" + } + ], + "readme": "A `rm -rf` for node.\n\nInstall with `npm install rimraf`, or just drop rimraf.js somewhere.\n\n## API\n\n`rimraf(f, callback)`\n\nThe callback will be called with an error if there is one. Certain\nerrors are handled for you:\n\n* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times\n before giving up.\n* `EMFILE` - If too many file descriptors get opened, rimraf will\n patiently wait until more become available.\n\n\n## rimraf.sync\n\nIt can remove stuff synchronously, too. But that's not so good. Use\nthe async API. It's better.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/rimraf/issues" + }, + "dependencies": { + "graceful-fs": "~1.1" + }, + "_id": "rimraf@2.0.3", + "dist": { + "shasum": "b440bcdcea339834bf98dbdb4a58c8b03a03c044" + }, + "_from": "rimraf@~2.0.2", + "_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.0.3.tgz" +} diff --git a/node_modules/grunt/node_modules/rimraf/rimraf.js b/node_modules/grunt/node_modules/rimraf/rimraf.js new file mode 100644 index 000000000..95b2de8b9 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/rimraf.js @@ -0,0 +1,161 @@ +module.exports = rimraf +rimraf.sync = rimrafSync + +var path = require("path") + , fs + +try { + // optional dependency + fs = require("graceful-fs") +} catch (er) { + fs = require("fs") +} + +var lstat = "lstat" +if (process.platform === "win32") { + // not reliable on windows prior to 0.7.9 + var v = process.version.replace(/^v/, '').split(/\.|-/).map(Number) + if (v[0] === 0 && (v[1] < 7 || v[1] == 7 && v[2] < 9)) { + lstat = "stat" + } +} +if (!fs[lstat]) lstat = "stat" +var lstatSync = lstat + "Sync" + +// for EMFILE handling +var timeout = 0 +exports.EMFILE_MAX = 1000 +exports.BUSYTRIES_MAX = 3 + +function rimraf (p, cb) { + + if (!cb) throw new Error("No callback passed to rimraf()") + + var busyTries = 0 + + rimraf_(p, function CB (er) { + if (er) { + if (er.code === "EBUSY" && busyTries < exports.BUSYTRIES_MAX) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, CB) + }, time) + } + + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) { + return setTimeout(function () { + rimraf_(p, CB) + }, timeout ++) + } + + // already gone + if (er.code === "ENOENT") er = null + } + + timeout = 0 + cb(er) + }) +} + +function rimraf_ (p, cb) { + fs[lstat](p, function (er, s) { + if (er) { + // already gone + if (er.code === "ENOENT") return cb() + // some other kind of error, permissions, etc. + return cb(er) + } + + return rm_(p, s, false, cb) + }) +} + + +var myGid = function myGid () { + var g = process.getgid && process.getgid() + myGid = function myGid () { return g } + return g +} + +var myUid = function myUid () { + var u = process.getuid && process.getuid() + myUid = function myUid () { return u } + return u +} + + +function writable (s) { + var mode = s.mode || 0777 + , uid = myUid() + , gid = myGid() + return (mode & 0002) + || (gid === s.gid && (mode & 0020)) + || (uid === s.uid && (mode & 0200)) +} + +function rm_ (p, s, didWritableCheck, cb) { + if (!didWritableCheck && !writable(s)) { + // make file writable + // user/group/world, doesn't matter at this point + // since it's about to get nuked. + return fs.chmod(p, s.mode | 0222, function (er) { + if (er) return cb(er) + rm_(p, s, true, cb) + }) + } + + if (!s.isDirectory()) { + return fs.unlink(p, cb) + } + + // directory + fs.readdir(p, function (er, files) { + if (er) return cb(er) + asyncForEach(files.map(function (f) { + return path.join(p, f) + }), function (file, cb) { + rimraf(file, cb) + }, function (er) { + if (er) return cb(er) + fs.rmdir(p, cb) + }) + }) +} + +function asyncForEach (list, fn, cb) { + if (!list.length) cb() + var c = list.length + , errState = null + list.forEach(function (item, i, list) { + fn(item, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (-- c === 0) return cb() + }) + }) +} + +// this looks simpler, but it will fail with big directory trees, +// or on slow stupid awful cygwin filesystems +function rimrafSync (p) { + try { + var s = fs[lstatSync](p) + } catch (er) { + if (er.code === "ENOENT") return + throw er + } + + if (!writable(s)) { + fs.chmodSync(p, s.mode | 0222) + } + + if (!s.isDirectory()) return fs.unlinkSync(p) + + fs.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f)) + }) + fs.rmdirSync(p) +} diff --git a/node_modules/grunt/node_modules/rimraf/test/run.sh b/node_modules/grunt/node_modules/rimraf/test/run.sh new file mode 100644 index 000000000..598f0163b --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/test/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e +for i in test-*.js; do + echo -n $i ... + bash setup.sh + node $i + ! [ -d target ] + echo "pass" +done +rm -rf target diff --git a/node_modules/grunt/node_modules/rimraf/test/setup.sh b/node_modules/grunt/node_modules/rimraf/test/setup.sh new file mode 100644 index 000000000..2602e6316 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/test/setup.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -e + +files=10 +folders=2 +depth=4 +target="$PWD/target" + +rm -rf target + +fill () { + local depth=$1 + local files=$2 + local folders=$3 + local target=$4 + + if ! [ -d $target ]; then + mkdir -p $target + fi + + local f + + f=$files + while [ $f -gt 0 ]; do + touch "$target/f-$depth-$f" + let f-- + done + + let depth-- + + if [ $depth -le 0 ]; then + return 0 + fi + + f=$folders + while [ $f -gt 0 ]; do + mkdir "$target/folder-$depth-$f" + fill $depth $files $folders "$target/d-$depth-$f" + let f-- + done +} + +fill $depth $files $folders $target + +# sanity assert +[ -d $target ] diff --git a/node_modules/grunt/node_modules/rimraf/test/test-async.js b/node_modules/grunt/node_modules/rimraf/test/test-async.js new file mode 100644 index 000000000..9c2e0b7be --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/test/test-async.js @@ -0,0 +1,5 @@ +var rimraf = require("../rimraf") + , path = require("path") +rimraf(path.join(__dirname, "target"), function (er) { + if (er) throw er +}) diff --git a/node_modules/grunt/node_modules/rimraf/test/test-fiber.js b/node_modules/grunt/node_modules/rimraf/test/test-fiber.js new file mode 100644 index 000000000..e69de29bb diff --git a/node_modules/grunt/node_modules/rimraf/test/test-sync.js b/node_modules/grunt/node_modules/rimraf/test/test-sync.js new file mode 100644 index 000000000..eb71f1047 --- /dev/null +++ b/node_modules/grunt/node_modules/rimraf/test/test-sync.js @@ -0,0 +1,3 @@ +var rimraf = require("../rimraf") + , path = require("path") +rimraf.sync(path.join(__dirname, "target")) diff --git a/node_modules/grunt/node_modules/underscore.string/.travis.yml b/node_modules/grunt/node_modules/underscore.string/.travis.yml new file mode 100644 index 000000000..ab27b29b7 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/.travis.yml @@ -0,0 +1,8 @@ +language: ruby +rvm: + - 1.9.3 + +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sleep 2 \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/Gemfile b/node_modules/grunt/node_modules/underscore.string/Gemfile new file mode 100644 index 000000000..f02482739 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/Gemfile @@ -0,0 +1,5 @@ +source :rubygems + +gem 'serve' +gem 'uglifier' +gem 'rake' \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/Gemfile.lock b/node_modules/grunt/node_modules/underscore.string/Gemfile.lock new file mode 100644 index 000000000..a6bb1e73a --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/Gemfile.lock @@ -0,0 +1,34 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (3.2.3) + i18n (~> 0.6) + multi_json (~> 1.0) + execjs (1.3.0) + multi_json (~> 1.0) + i18n (0.6.0) + multi_json (1.2.0) + rack (1.4.1) + rack-test (0.6.1) + rack (>= 1.0) + rake (0.9.2.2) + serve (1.5.1) + activesupport (~> 3.0) + i18n + rack (~> 1.2) + rack-test (~> 0.5) + tilt (~> 1.3) + tzinfo + tilt (1.3.3) + tzinfo (0.3.33) + uglifier (1.2.4) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + rake + serve + uglifier diff --git a/node_modules/grunt/node_modules/underscore.string/README.markdown b/node_modules/grunt/node_modules/underscore.string/README.markdown new file mode 100644 index 000000000..d2244b578 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/README.markdown @@ -0,0 +1,668 @@ +# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) # + + + +Javascript lacks complete string manipulation operations. +This an attempt to fill that gap. List of build-in methods can be found +for example from [Dive Into JavaScript][d]. + +[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object + + +As name states this an extension for [Underscore.js][u], but it can be used +independently from **_s**-global variable. But with Underscore.js you can +use Object-Oriented style and chaining: + +[u]: http://documentcloud.github.com/underscore/ + +```javascript +_(" epeli ").chain().trim().capitalize().value() +=> "Epeli" +``` + +## Download ## + + * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb* + * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb* + + +## Node.js installation ## + +**npm package** + + npm install underscore.string + +**Standalone usage**: + +```javascript +var _s = require('underscore.string'); +``` + +**Integrate with Underscore.js**: + +```javascript +var _ = require('underscore'); + +// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains) +_.str = require('underscore.string'); + +// Mix in non-conflict functions to Underscore namespace if you want +_.mixin(_.str.exports()); + +// All functions, include conflict, will be available through _.str object +_.str.include('Underscore.string', 'string'); // => true +``` + +## String Functions ## + +For availability of functions in this way you need to mix in Underscore.string functions: + +```javascript +_.mixin(_.string.exports()); +``` + +otherwise functions from examples will be available through _.string or _.str objects: + +```javascript +_.str.capitalize('epeli') +=> "Epeli" +``` + +**capitalize** _.capitalize(string) + +Converts first letter of the string to uppercase. + +```javascript +_.capitalize("foo Bar") +=> "Foo Bar" +``` + +**chop** _.chop(string, step) + +```javascript +_.chop('whitespace', 3) +=> ['whi','tes','pac','e'] +``` + +**clean** _.clean(str) + +Compress some whitespaces to one. + +```javascript +_.clean(" foo bar ") +=> 'foo bar' +``` + +**chars** _.chars(str) + +```javascript +_.chars('Hello') +=> ['H','e','l','l','o'] +``` + +**includes** _.includes(string, substring) + +Tests if string contains a substring. + +```javascript +_.includes("foobar", "ob") +=> true +``` + +**include** available only through _.str object, because Underscore has function with the same name. + +```javascript +_.str.include("foobar", "ob") +=> true +``` + +**includes** function was removed + +But you can create it in this way, for compatibility with previous versions: + +```javascript +_.includes = _.str.include +``` + +**count** _.count(string, substring) + +```javascript +_('Hello world').count('l') +=> 3 +``` + +**escapeHTML** _.escapeHTML(string) + +Converts HTML special characters to their entity equivalents. + +```javascript +_('
          Blah blah blah
          ').escapeHTML(); +=> '<div>Blah blah blah</div>' +``` + +**unescapeHTML** _.unescapeHTML(string) + +Converts entity characters to HTML equivalents. + +```javascript +_('<div>Blah blah blah</div>').unescapeHTML(); +=> '
          Blah blah blah
          ' +``` + +**insert** _.insert(string, index, substing) + +```javascript +_('Hello ').insert(6, 'world') +=> 'Hello world' +``` + +**isBlank** _.isBlank(string) + +```javascript +_('').isBlank(); // => true +_('\n').isBlank(); // => true +_(' ').isBlank(); // => true +_('a').isBlank(); // => false +``` + +**join** _.join(separator, *strings) + +Joins strings together with given separator + +```javascript +_.join(" ", "foo", "bar") +=> "foo bar" +``` + +**lines** _.lines(str) + +```javascript +_.lines("Hello\nWorld") +=> ["Hello", "World"] +``` + +**reverse** available only through _.str object, because Underscore has function with the same name. + +Return reversed string: + +```javascript +_.str.reverse("foobar") +=> 'raboof' +``` + +**splice** _.splice(string, index, howmany, substring) + +Like a array splice. + +```javascript +_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli') +=> 'https://edtsech@bitbucket.org/epeli/underscore.strings' +``` + +**startsWith** _.startsWith(string, starts) + +This method checks whether string starts with starts. + +```javascript +_("image.gif").startsWith("image") +=> true +``` + +**endsWith** _.endsWith(string, ends) + +This method checks whether string ends with ends. + +```javascript +_("image.gif").endsWith("gif") +=> true +``` + +**succ** _.succ(str) + +Returns the successor to str. + +```javascript +_('a').succ() +=> 'b' + +_('A').succ() +=> 'B' +``` + +**supplant** + +Supplant function was removed, use Underscore.js [template function][p]. + +[p]: http://documentcloud.github.com/underscore/#template + +**strip** alias for *trim* + +**lstrip** alias for *ltrim* + +**rstrip** alias for *rtrim* + +**titleize** _.titleize(string) + +```javascript +_('my name is epeli').titleize() +=> 'My Name Is Epeli' +``` + +**camelize** _.camelize(string) + +Converts underscored or dasherized string to a camelized one + +```javascript +_('-moz-transform').camelize() +=> 'MozTransform' +``` + +**classify** _.classify(string) + +Converts string to camelized class name + +```javascript +_('some_class_name').classify() +=> 'SomeClassName' +``` + +**underscored** _.underscored(string) + +Converts a camelized or dasherized string into an underscored one + +```javascript +_('MozTransform').underscored() +=> 'moz_transform' +``` + +**dasherize** _.dasherize(string) + +Converts a underscored or camelized string into an dasherized one + +```javascript +_('MozTransform').dasherize() +=> '-moz-transform' +``` + +**humanize** _.humanize(string) + +Converts an underscored, camelized, or dasherized string into a humanized one. +Also removes beginning and ending whitespace, and removes the postfix '_id'. + +```javascript +_(' capitalize dash-CamelCase_underscore trim ').humanize() +=> 'Capitalize dash camel case underscore trim' +``` + +**trim** _.trim(string, [characters]) + +trims defined characters from begining and ending of the string. +Defaults to whitespace characters. + +```javascript +_.trim(" foobar ") +=> "foobar" + +_.trim("_-foobar-_", "_-") +=> "foobar" +``` + + +**ltrim** _.ltrim(string, [characters]) + +Left trim. Similar to trim, but only for left side. + + +**rtrim** _.rtrim(string, [characters]) + +Right trim. Similar to trim, but only for right side. + +**truncate** _.truncate(string, length, truncateString) + +```javascript +_('Hello world').truncate(5) +=> 'Hello...' + +_('Hello').truncate(10) +=> 'Hello' +``` + +**prune** _.prune(string, length, pruneString) + +Elegant version of truncate. +Makes sure the pruned string does not exceed the original length. +Avoid half-chopped words when truncating. + +```javascript +_('Hello, world').prune(5) +=> 'Hello...' + +_('Hello, world').prune(8) +=> 'Hello...' + +_('Hello, world').prune(5, ' (read a lot more)') +=> 'Hello, world' (as adding "(read a lot more)" would be longer than the original string) + +_('Hello, cruel world').prune(15) +=> 'Hello, cruel...' + +_('Hello').prune(10) +=> 'Hello' +``` + +**words** _.words(str, delimiter=" ") + +Split string by delimiter (String or RegExp), ' ' by default. + +```javascript +_.words("I love you") +=> ["I","love","you"] + +_.words("I_love_you", "_") +=> ["I","love","you"] + +_.words("I-love-you", /-/) +=> ["I","love","you"] +``` + +**sprintf** _.sprintf(string format, *arguments) + +C like string formatting. +Credits goes to [Alexandru Marasteanu][o]. +For more detailed documentation, see the [original page][o]. + +[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript + +```javascript +_.sprintf("%.1f", 1.17) +"1.2" +``` + +**pad** _.pad(str, length, [padStr, type]) + +pads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`" "`). `padStr` is truncated to a single character if necessary. + +```javascript +_.pad("1", 8) +-> " 1"; + +_.pad("1", 8, '0') +-> "00000001"; + +_.pad("1", 8, '0', 'right') +-> "10000000"; + +_.pad("1", 8, '0', 'both') +-> "00001000"; + +_.pad("1", 8, 'bleepblorp', 'both') +-> "bbbb1bbb"; +``` + +**lpad** _.lpad(str, length, [padStr]) + +left-pad a string. Alias for `pad(str, length, padStr, 'left')` + +```javascript +_.lpad("1", 8, '0') +-> "00000001"; +``` + +**rpad** _.rpad(str, length, [padStr]) + +right-pad a string. Alias for `pad(str, length, padStr, 'right')` + +```javascript +_.rpad("1", 8, '0') +-> "10000000"; +``` + +**lrpad** _.lrpad(str, length, [padStr]) + +left/right-pad a string. Alias for `pad(str, length, padStr, 'both')` + +```javascript +_.lrpad("1", 8, '0') +-> "00001000"; +``` + +**center** alias for **lrpad** + +**ljust** alias for *rpad* + +**rjust** alias for *lpad* + +**toNumber** _.toNumber(string, [decimals]) + +Parse string to number. Returns NaN if string can't be parsed to number. + +```javascript +_('2.556').toNumber() +=> 3 + +_('2.556').toNumber(1) +=> 2.6 +``` + +**strRight** _.strRight(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRight('_') +=> "is_a_test_string"; +``` + +**strRightBack** _.strRightBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRightBack('_') +=> "string"; +``` + +**strLeft** _.strLeft(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeft('_') +=> "This"; +``` + +**strLeftBack** _.strLeftBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeftBack('_') +=> "This_is_a_test"; +``` + +**stripTags** + +Removes all html tags from string. + +```javascript +_('a link').stripTags() +=> 'a link' + +_('a link').stripTags() +=> 'a linkalert("hello world!")' +``` + +**toSentence** _.toSentence(array, [delimiter, lastDelimiter]) + +Join an array into a human readable sentence. + +```javascript +_.toSentence(['jQuery', 'Mootools', 'Prototype']) +=> 'jQuery, Mootools and Prototype'; + +_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ') +=> 'jQuery, Mootools unt Prototype'; +``` + +**repeat** _.repeat(string, count, [separator]) + +Repeats a string count times. + +```javascript +_.repeat("foo", 3) +=> 'foofoofoo'; + +_.repeat("foo", 3, "bar") +=> 'foobarfoobarfoo' +``` + +**slugify** _.slugify(string) + +Transform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash. + +```javascript +_.slugify("Un éléphant à l'orée du bois") +=> 'un-elephant-a-loree-du-bois'; +``` + +***Caution: this function is charset dependent*** + +## Roadmap ## + +Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. + +## Changelog ## + +### 2.0.0 ### + +* Added prune, humanize functions +* Added _.string (_.str) namespace for Underscore.string library +* Removed includes function + +#### Problems + +We lose two things for `include` and `reverse` methods from `_.string`: + +* Calls like `_('foobar').include('bar')` aren't available; +* Chaining isn't available too. + +But if you need this functionality you can create aliases for conflict functions which will be convenient for you: + +```javascript +_.mixin({ + includeString: _.str.include, + reverseString: _.str.reverse +}) + +// Now wrapper calls and chaining are available. +_('foobar').chain().reverseString().includeString('rab').value() +``` + +#### Standalone Usage + +If you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias +But of course you can just reassign `_` variable with `_.string` + +```javascript +_ = _.string +``` +### 2.2.0 ### + +* Capitalize method behavior changed +* Various perfomance tweaks + +### 2.1.1### + +* Fixed words method bug +* Added classify method + +### 2.1.0 ### + +* AMD support +* Added toSentence method +* Added slugify method +* Lots of speed optimizations + +### 2.0.0 ### + +For upgrading to this version you need to mix in Underscore.string library to Underscore object: + +```javascript +_.mixin(_.string.exports()); +``` + +and all non-conflict Underscore.string functions will be available through Underscore object. +Also function `includes` has been removed, you should replace this function by `_.str.include` +or create alias `_.includes = _.str.include` and all your code will work fine. + +### 1.1.6 ### + +* Fixed reverse and truncate +* Added isBlank, stripTags, inlude(alias for includes) +* Added uglifier compression + +### 1.1.5 ### + +* Added strRight, strRightBack, strLeft, strLeftBack + +### 1.1.4 ### + +* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust +* Integration with Underscore 1.1.6 + +### 1.1.3 ### + +* Added methods: underscored, camelize, dasherize +* Support newer version of npm + +### 1.1.2 ### + +* Created functions: lines, chars, words functions + +### 1.0.2 ### + +* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible) +* Removed 'reverse' function, because this function override underscore.js 'reverse' + +## Contribute ## + +* Fork & pull request. Don't forget about tests. +* If you planning add some feature please create issue before. + +Otherwise changes will be rejected. + +## Contributors list ## + +* Esa-Matti Suuronen (), +* Edward Tsech , +* Sasha Koss (), +* Vladimir Dronnikov , +* Pete Kruckenberg (), +* Paul Chavard (), +* Ed Finkler () +* Pavel Pravosud +* Anton Lindqvist () + +## Licence ## + +The MIT License + +Copyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt/node_modules/underscore.string/Rakefile b/node_modules/grunt/node_modules/underscore.string/Rakefile new file mode 100644 index 000000000..baa164cd9 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/Rakefile @@ -0,0 +1,28 @@ +# encoding: utf-8 +task default: :test + +desc 'Use UglifyJS to compress Underscore.string' +task :build do + require 'uglifier' + source = File.read('lib/underscore.string.js') + compressed = Uglifier.compile(source, copyright: false) + File.open('dist/underscore.string.min.js', 'w'){ |f| f.write compressed } + compression_rate = compressed.length.to_f/source.length + puts "compressed dist/underscore.string.min.js: #{compressed.length}/#{source.length} #{(compression_rate * 100).round}%" +end + +desc 'Run tests' +task :test do + pid = spawn('bundle exec serve', err: '/dev/null') + sleep 2 + + puts "Running underscore.string test suite." + result1 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test.html"} + + puts "Running Underscore test suite." + result2 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test_underscore/test.html"} + + Process.kill 'INT', pid + + exit(result1 && result2 ? 0 : 1) +end \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js b/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js new file mode 100644 index 000000000..cd436e192 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js @@ -0,0 +1 @@ +(function(a){"use strict";var b=String.prototype.trim,c=String.prototype.trimRight,d=String.prototype.trimLeft,e=function(a){return a*1||0},f=function(a,b,c){a+="",b=~~b;for(var d=[];b>0;d[--b]=a);return d.join(c==null?"":c)},g=function(a){return Array.prototype.slice.call(a)},h=function(a){return a!=null?"["+m.escapeRegExp(""+a)+"]":"\\s"},i={lt:"<",gt:">",quot:'"',apos:"'",amp:"&"},j={};for(var k in i)j[i[k]]=k;var l=function(){function a(a){return Object.prototype.toString.call(a).slice(8,-1).toLowerCase()}var b=f,c=function(){return c.cache.hasOwnProperty(arguments[0])||(c.cache[arguments[0]]=c.parse(arguments[0])),c.format.call(null,c.cache[arguments[0]],arguments)};return c.format=function(c,d){var e=1,f=c.length,g="",h,i=[],j,k,m,n,o,p;for(j=0;j=0?"+"+h:h,o=m[4]?m[4]=="0"?"0":m[4].charAt(1):" ",p=m[6]-String(h).length,n=m[6]?b(o,p):"",i.push(m[5]?h+n:n+h)}}return i.join("")},c.cache={},c.parse=function(a){var b=a,c=[],d=[],e=0;while(b){if((c=/^[^\x25]+/.exec(b))!==null)d.push(c[0]);else if((c=/^\x25{2}/.exec(b))!==null)d.push("%");else{if((c=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(b))===null)throw new Error("[_.sprintf] huh?");if(c[2]){e|=1;var f=[],g=c[2],h=[];if((h=/^([a-z_][a-z_\d]*)/i.exec(g))===null)throw new Error("[_.sprintf] huh?");f.push(h[1]);while((g=g.substring(h[0].length))!=="")if((h=/^\.([a-z_][a-z_\d]*)/i.exec(g))!==null)f.push(h[1]);else{if((h=/^\[(\d+)\]/.exec(g))===null)throw new Error("[_.sprintf] huh?");f.push(h[1])}c[2]=f}else e|=2;if(e===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");d.push(c)}b=b.substring(c[0].length)}return d},c}(),m={VERSION:"2.1.1",isBlank:function(a){return/^\s*$/.test(a)},stripTags:function(a){return(""+a).replace(/<\/?[^>]+>/g,"")},capitalize:function(a){return a+="",a.charAt(0).toUpperCase()+a.substring(1)},chop:function(a,b){a+="",b=~~b||a.length;var c=[];for(var d=0;d"']/g,function(a){return"&"+j[a]+";"})},unescapeHTML:function(a){return(""+a).replace(/\&([^;]+);/g,function(a,b){var c;return b in i?i[b]:(c=b.match(/^#x([\da-fA-F]+)$/))?String.fromCharCode(parseInt(c[1],16)):(c=b.match(/^#(\d+)$/))?String.fromCharCode(~~c[1]):a})},escapeRegExp:function(a){return a.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1")},insert:function(a,b,c){var d=m.chars(a);return d.splice(~~b,0,""+c),d.join("")},include:function(a,b){return!!~(""+a).indexOf(b)},join:function(){var a=g(arguments);return a.join(a.shift())},lines:function(a){return(""+a).split("\n")},reverse:function(a){return m.chars(a).reverse().join("")},splice:function(a,b,c,d){var e=m.chars(a);return e.splice(~~b,~~c,d),e.join("")},startsWith:function(a,b){return a+="",b+="",a.length>=b.length&&a.substring(0,b.length)===b},endsWith:function(a,b){return a+="",b+="",a.length>=b.length&&a.substring(a.length-b.length)===b},succ:function(a){a+="";var b=m.chars(a);return b.splice(a.length-1,1,String.fromCharCode(a.charCodeAt(a.length-1)+1)),b.join("")},titleize:function(a){return(""+a).replace(/\b./g,function(a){return a.toUpperCase()})},camelize:function(a){return m.trim(a).replace(/[-_\s]+(.)?/g,function(a,b){return b&&b.toUpperCase()})},underscored:function(a){return m.trim(a).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(a){return m.trim(a).replace(/[_\s]+/g,"-").replace(/([A-Z])/g,"-$1").replace(/-+/g,"-").toLowerCase()},classify:function(a){return a+="",m.titleize(a.replace(/_/g," ")).replace(/\s/g,"")},humanize:function(a){return m.capitalize(this.underscored(a).replace(/_id$/,"").replace(/_/g," "))},trim:function(a,c){return a+="",!c&&b?b.call(a):(c=h(c),a.replace(new RegExp("^"+c+"+|"+c+"+$","g"),""))},ltrim:function(a,b){return a+="",!b&&d?d.call(a):(b=h(b),a.replace(new RegExp("^"+b+"+"),""))},rtrim:function(a,b){return a+="",!b&&c?c.call(a):(b=h(b),a.replace(new RegExp(b+"+$"),""))},truncate:function(a,b,c){return a+="",c=c||"...",b=~~b,a.length>b?a.slice(0,b)+c:a},prune:function(a,b,c){a+="",b=~~b,c=c!=null?""+c:"...";var d,e,f=a.replace(/\W/g,function(a){return a.toUpperCase()!==a.toLowerCase()?"A":" "});return e=f.charAt(b),d=f.slice(0,b),e&&e.match(/\S/)&&(d=d.replace(/\s\S+$/,"")),d=m.rtrim(d),(d+c).length>a.length?a:a.substring(0,d.length)+c},words:function(a,b){return m.trim(a,b).split(b||/\s+/)},pad:function(a,b,c,d){a+="";var e=0;b=~~b,c?c.length>1&&(c=c.charAt(0)):c=" ";switch(d){case"right":return e=b-a.length,a+f(c,e);case"both":return e=b-a.length,f(c,Math.ceil(e/2))+a+f(c,Math.floor(e/2));default:return e=b-a.length,f(c,e)+a}},lpad:function(a,b,c){return m.pad(a,b,c)},rpad:function(a,b,c){return m.pad(a,b,c,"right")},lrpad:function(a,b,c){return m.pad(a,b,c,"both")},sprintf:l,vsprintf:function(a,b){return b.unshift(a),l.apply(null,b)},toNumber:function(a,b){a+="";var c=e(e(a).toFixed(~~b));return c===0&&!a.match(/^0+$/)?Number.NaN:c},strRight:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.indexOf(b):-1;return~c?a.slice(c+b.length,a.length):a},strRightBack:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.lastIndexOf(b):-1;return~c?a.slice(c+b.length,a.length):a},strLeft:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.indexOf(b):-1;return~c?a.slice(0,c):a},strLeftBack:function(a,b){a+="",b=b!=null?""+b:b;var c=a.lastIndexOf(b);return~c?a.slice(0,c):a},toSentence:function(a,b,c){b||(b=", "),c||(c=" and ");var d=a.length,e="";for(var f=0;f +// Underscore.strings is freely distributable under the terms of the MIT license. +// Documentation: https://github.com/epeli/underscore.string +// Some code is borrowed from MooTools and Alexandru Marasteanu. + +// Version 2.2.0rc + +(function(root){ + 'use strict'; + + // Defining helper functions. + + var nativeTrim = String.prototype.trim; + var nativeTrimRight = String.prototype.trimRight; + var nativeTrimLeft = String.prototype.trimLeft; + + var parseNumber = function(source) { return source * 1 || 0; }; + + var strRepeat = function(str, qty, separator){ + // ~~var — is the fastest available way to convert anything to Integer in javascript. + // We'll use it extensively in this lib. + str += ''; qty = ~~qty; + for (var repeat = []; qty > 0; repeat[--qty] = str) {} + return repeat.join(separator == null ? '' : separator); + }; + + var slice = function(a){ + return Array.prototype.slice.call(a); + }; + + var defaultToWhiteSpace = function(characters){ + if (characters != null) { + return '[' + _s.escapeRegExp(''+characters) + ']'; + } + return '\\s'; + }; + + var escapeChars = { + lt: '<', + gt: '>', + quot: '"', + apos: "'", + amp: '&' + }; + + var reversedEscapeChars = {}; + for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; } + + // sprintf() for JavaScript 0.7-beta1 + // http://www.diveintojavascript.com/projects/javascript-sprintf + // + // Copyright (c) Alexandru Marasteanu + // All rights reserved. + + var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + + var str_repeat = strRepeat; + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw new Error('[_.sprintf] huh?'); + } + } + } + else { + throw new Error('[_.sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw new Error('[_.sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; + })(); + + + + // Defining underscore.string + + var _s = { + + VERSION: '2.2.0rc', + + isBlank: function(str){ + return (/^\s*$/).test(str); + }, + + stripTags: function(str){ + return (''+str).replace(/<\/?[^>]+>/g, ''); + }, + + capitalize : function(str) { + str += ''; + return str.charAt(0).toUpperCase() + str.substring(1); + }, + + chop: function(str, step){ + str = str+''; + step = ~~step || str.length; + var arr = []; + for (var i = 0; i < str.length; i += step) + arr.push(str.slice(i,i + step)); + return arr; + }, + + clean: function(str){ + return _s.strip(str).replace(/\s+/g, ' '); + }, + + count: function(str, substr){ + str += ''; substr += ''; + return str.split(substr).length - 1; + }, + + chars: function(str) { + return (''+str).split(''); + }, + + escapeHTML: function(str) { + return (''+str).replace(/[&<>"']/g, function(match){ return '&' + reversedEscapeChars[match] + ';'; }); + }, + + unescapeHTML: function(str) { + return (''+str).replace(/\&([^;]+);/g, function(entity, entityCode){ + var match; + + if (entityCode in escapeChars) { + return escapeChars[entityCode]; + } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { + return String.fromCharCode(parseInt(match[1], 16)); + } else if (match = entityCode.match(/^#(\d+)$/)) { + return String.fromCharCode(~~match[1]); + } else { + return entity; + } + }); + }, + + escapeRegExp: function(str){ + // From MooTools core 1.2.4 + return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + insert: function(str, i, substr){ + var arr = _s.chars(str); + arr.splice(~~i, 0, ''+substr); + return arr.join(''); + }, + + include: function(str, needle){ + return !!~(''+str).indexOf(needle); + }, + + join: function() { + var args = slice(arguments); + return args.join(args.shift()); + }, + + lines: function(str) { + return (''+str).split("\n"); + }, + + reverse: function(str){ + return _s.chars(str).reverse().join(''); + }, + + splice: function(str, i, howmany, substr){ + var arr = _s.chars(str); + arr.splice(~~i, ~~howmany, substr); + return arr.join(''); + }, + + startsWith: function(str, starts){ + str += ''; starts += ''; + return str.length >= starts.length && str.substring(0, starts.length) === starts; + }, + + endsWith: function(str, ends){ + str += ''; ends += ''; + return str.length >= ends.length && str.substring(str.length - ends.length) === ends; + }, + + succ: function(str){ + str += ''; + var arr = _s.chars(str); + arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1)); + return arr.join(''); + }, + + titleize: function(str){ + return (''+str).replace(/\b./g, function(ch){ return ch.toUpperCase(); }); + }, + + camelize: function(str){ + return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, chr){ + return chr && chr.toUpperCase(); + }); + }, + + underscored: function(str){ + return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); + }, + + dasherize: function(str){ + return _s.trim(str).replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase(); + }, + + classify: function(str){ + str += ''; + return _s.titleize(str.replace(/_/g, ' ')).replace(/\s/g, '') + }, + + humanize: function(str){ + return _s.capitalize(this.underscored(str).replace(/_id$/,'').replace(/_/g, ' ')); + }, + + trim: function(str, characters){ + str += ''; + if (!characters && nativeTrim) { return nativeTrim.call(str); } + characters = defaultToWhiteSpace(characters); + return str.replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), ''); + }, + + ltrim: function(str, characters){ + str+=''; + if (!characters && nativeTrimLeft) { + return nativeTrimLeft.call(str); + } + characters = defaultToWhiteSpace(characters); + return str.replace(new RegExp('^' + characters + '+'), ''); + }, + + rtrim: function(str, characters){ + str+=''; + if (!characters && nativeTrimRight) { + return nativeTrimRight.call(str); + } + characters = defaultToWhiteSpace(characters); + return str.replace(new RegExp(characters + '+$'), ''); + }, + + truncate: function(str, length, truncateStr){ + str += ''; truncateStr = truncateStr || '...'; + length = ~~length; + return str.length > length ? str.slice(0, length) + truncateStr : str; + }, + + /** + * _s.prune: a more elegant version of truncate + * prune extra chars, never leaving a half-chopped word. + * @author github.com/sergiokas + */ + prune: function(str, length, pruneStr){ + str += ''; length = ~~length; + pruneStr = pruneStr != null ? ''+pruneStr : '...'; + + var pruned, borderChar, template = str.replace(/\W/g, function(ch){ + return (ch.toUpperCase() !== ch.toLowerCase()) ? 'A' : ' '; + }); + + borderChar = template.charAt(length); + + pruned = template.slice(0, length); + + // Check if we're in the middle of a word + if (borderChar && borderChar.match(/\S/)) + pruned = pruned.replace(/\s\S+$/, ''); + + pruned = _s.rtrim(pruned); + + return (pruned+pruneStr).length > str.length ? str : str.substring(0, pruned.length)+pruneStr; + }, + + words: function(str, delimiter) { + return _s.trim(str, delimiter).split(delimiter || /\s+/); + }, + + pad: function(str, length, padStr, type) { + str += ''; + + var padlen = 0; + + length = ~~length; + + if (!padStr) { + padStr = ' '; + } else if (padStr.length > 1) { + padStr = padStr.charAt(0); + } + + switch(type) { + case 'right': + padlen = (length - str.length); + return str + strRepeat(padStr, padlen); + case 'both': + padlen = (length - str.length); + return strRepeat(padStr, Math.ceil(padlen/2)) + + str + + strRepeat(padStr, Math.floor(padlen/2)); + default: // 'left' + padlen = (length - str.length); + return strRepeat(padStr, padlen) + str; + } + }, + + lpad: function(str, length, padStr) { + return _s.pad(str, length, padStr); + }, + + rpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'right'); + }, + + lrpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'both'); + }, + + sprintf: sprintf, + + vsprintf: function(fmt, argv){ + argv.unshift(fmt); + return sprintf.apply(null, argv); + }, + + toNumber: function(str, decimals) { + str += ''; + var num = parseNumber(parseNumber(str).toFixed(~~decimals)); + return num === 0 && !str.match(/^0+$/) ? Number.NaN : num; + }, + + strRight: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = !sep ? -1 : str.indexOf(sep); + return ~pos ? str.slice(pos+sep.length, str.length) : str; + }, + + strRightBack: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = !sep ? -1 : str.lastIndexOf(sep); + return ~pos ? str.slice(pos+sep.length, str.length) : str; + }, + + strLeft: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = !sep ? -1 : str.indexOf(sep); + return ~pos ? str.slice(0, pos) : str; + }, + + strLeftBack: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = str.lastIndexOf(sep); + return ~pos ? str.slice(0, pos) : str; + }, + + toSentence: function(array, separator, lastSeparator) { + separator || (separator = ', '); + lastSeparator || (lastSeparator = ' and '); + var length = array.length, str = ''; + + for (var i = 0; i < length; i++) { + str += array[i]; + if (i === (length - 2)) { str += lastSeparator; } + else if (i < (length - 1)) { str += separator; } + } + + return str; + }, + + slugify: function(str) { + var from = "ąàáäâãćęèéëêìíïîłńòóöôõùúüûñçżź", + to = "aaaaaaceeeeeiiiilnooooouuuunczz", + regex = new RegExp(defaultToWhiteSpace(from), 'g'); + + str = (''+str).toLowerCase(); + + str = str.replace(regex, function(ch){ + var index = from.indexOf(ch); + return to.charAt(index) || '-'; + }); + + return _s.trim(str.replace(/[^\w\s-]/g, '').replace(/[-\s]+/g, '-'), '-'); + }, + + exports: function() { + var result = {}; + + for (var prop in this) { + if (!this.hasOwnProperty(prop) || ~_s.words('include contains reverse').indexOf(prop)) continue; + result[prop] = this[prop]; + } + + return result; + }, + + repeat: strRepeat + }; + + // Aliases + + _s.strip = _s.trim; + _s.lstrip = _s.ltrim; + _s.rstrip = _s.rtrim; + _s.center = _s.lrpad; + _s.rjust = _s.lpad; + _s.ljust = _s.rpad; + _s.contains = _s.include; + + // CommonJS module is defined + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + // Export module + module.exports = _s; + } + exports._s = _s; + + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore.string', function() { + return _s; + }); + + } else { + // Integrate with Underscore.js if defined + // or create our own underscore object. + root._ = root._ || {}; + root._.string = root._.str = _s; + } + +}(this || window)); diff --git a/node_modules/grunt/node_modules/underscore.string/package.json b/node_modules/grunt/node_modules/underscore.string/package.json new file mode 100644 index 000000000..f598f6465 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/package.json @@ -0,0 +1,76 @@ +{ + "name": "underscore.string", + "version": "2.2.1", + "description": "String manipulation extensions for Underscore.js javascript library.", + "homepage": "http://epeli.github.com/underscore.string/", + "contributors": [ + { + "name": "Esa-Matti Suuronen", + "email": "esa-matti@suuronen.org", + "url": "http://esa-matti.suuronen.org/" + }, + { + "name": "Edward Tsech", + "email": "edtsech@gmail.com" + }, + { + "name": "Sasha Koss", + "email": "kossnocorp@gmail.com", + "url": "http://koss.nocorp.me/" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Pete Kruckenberg", + "email": "https://github.com/kruckenb", + "url": "" + }, + { + "name": "Paul Chavard", + "email": "paul@chavard.net", + "url": "" + }, + { + "name": "Ed Finkler", + "email": "coj@funkatron.com", + "url": "" + }, + { + "name": "Pavel Pravosud", + "email": "rwz@duckroll.ru" + } + ], + "keywords": [ + "underscore", + "string" + ], + "main": "./lib/underscore.string", + "directories": { + "lib": "./lib" + }, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/epeli/underscore.string.git" + }, + "bugs": { + "url": "https://github.com/epeli/underscore.string/issues" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "readme": "# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) #\n\n\n\nJavascript lacks complete string manipulation operations.\nThis an attempt to fill that gap. List of build-in methods can be found\nfor example from [Dive Into JavaScript][d].\n\n[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object\n\n\nAs name states this an extension for [Underscore.js][u], but it can be used\nindependently from **_s**-global variable. But with Underscore.js you can\nuse Object-Oriented style and chaining:\n\n[u]: http://documentcloud.github.com/underscore/\n\n```javascript\n_(\" epeli \").chain().trim().capitalize().value()\n=> \"Epeli\"\n```\n\n## Download ##\n\n * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb*\n * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb*\n\n\n## Node.js installation ##\n\n**npm package**\n\n npm install underscore.string\n\n**Standalone usage**:\n\n```javascript\nvar _s = require('underscore.string');\n```\n\n**Integrate with Underscore.js**:\n\n```javascript\nvar _ = require('underscore');\n\n// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)\n_.str = require('underscore.string');\n\n// Mix in non-conflict functions to Underscore namespace if you want\n_.mixin(_.str.exports());\n\n// All functions, include conflict, will be available through _.str object\n_.str.include('Underscore.string', 'string'); // => true\n```\n\n## String Functions ##\n\nFor availability of functions in this way you need to mix in Underscore.string functions:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\notherwise functions from examples will be available through _.string or _.str objects:\n\n```javascript\n_.str.capitalize('epeli')\n=> \"Epeli\"\n```\n\n**capitalize** _.capitalize(string)\n\nConverts first letter of the string to uppercase.\n\n```javascript\n_.capitalize(\"foo Bar\")\n=> \"Foo Bar\"\n```\n\n**chop** _.chop(string, step)\n\n```javascript\n_.chop('whitespace', 3)\n=> ['whi','tes','pac','e']\n```\n\n**clean** _.clean(str)\n\nCompress some whitespaces to one.\n\n```javascript\n_.clean(\" foo bar \")\n=> 'foo bar'\n```\n\n**chars** _.chars(str)\n\n```javascript\n_.chars('Hello')\n=> ['H','e','l','l','o']\n```\n\n**includes** _.includes(string, substring)\n\nTests if string contains a substring.\n\n```javascript\n_.includes(\"foobar\", \"ob\")\n=> true\n```\n\n**include** available only through _.str object, because Underscore has function with the same name.\n\n```javascript\n_.str.include(\"foobar\", \"ob\")\n=> true\n```\n\n**includes** function was removed\n\nBut you can create it in this way, for compatibility with previous versions:\n\n```javascript\n_.includes = _.str.include\n```\n\n**count** _.count(string, substring)\n\n```javascript\n_('Hello world').count('l')\n=> 3\n```\n\n**escapeHTML** _.escapeHTML(string)\n\nConverts HTML special characters to their entity equivalents.\n\n```javascript\n_('
          Blah blah blah
          ').escapeHTML();\n=> '<div>Blah blah blah</div>'\n```\n\n**unescapeHTML** _.unescapeHTML(string)\n\nConverts entity characters to HTML equivalents.\n\n```javascript\n_('<div>Blah blah blah</div>').unescapeHTML();\n=> '
          Blah blah blah
          '\n```\n\n**insert** _.insert(string, index, substing)\n\n```javascript\n_('Hello ').insert(6, 'world')\n=> 'Hello world'\n```\n\n**isBlank** _.isBlank(string)\n\n```javascript\n_('').isBlank(); // => true\n_('\\n').isBlank(); // => true\n_(' ').isBlank(); // => true\n_('a').isBlank(); // => false\n```\n\n**join** _.join(separator, *strings)\n\nJoins strings together with given separator\n\n```javascript\n_.join(\" \", \"foo\", \"bar\")\n=> \"foo bar\"\n```\n\n**lines** _.lines(str)\n\n```javascript\n_.lines(\"Hello\\nWorld\")\n=> [\"Hello\", \"World\"]\n```\n\n**reverse** available only through _.str object, because Underscore has function with the same name.\n\nReturn reversed string:\n\n```javascript\n_.str.reverse(\"foobar\")\n=> 'raboof'\n```\n\n**splice** _.splice(string, index, howmany, substring)\n\nLike a array splice.\n\n```javascript\n_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli')\n=> 'https://edtsech@bitbucket.org/epeli/underscore.strings'\n```\n\n**startsWith** _.startsWith(string, starts)\n\nThis method checks whether string starts with starts.\n\n```javascript\n_(\"image.gif\").startsWith(\"image\")\n=> true\n```\n\n**endsWith** _.endsWith(string, ends)\n\nThis method checks whether string ends with ends.\n\n```javascript\n_(\"image.gif\").endsWith(\"gif\")\n=> true\n```\n\n**succ** _.succ(str)\n\nReturns the successor to str.\n\n```javascript\n_('a').succ()\n=> 'b'\n\n_('A').succ()\n=> 'B'\n```\n\n**supplant**\n\nSupplant function was removed, use Underscore.js [template function][p].\n\n[p]: http://documentcloud.github.com/underscore/#template\n\n**strip** alias for *trim*\n\n**lstrip** alias for *ltrim*\n\n**rstrip** alias for *rtrim*\n\n**titleize** _.titleize(string)\n\n```javascript\n_('my name is epeli').titleize()\n=> 'My Name Is Epeli'\n```\n\n**camelize** _.camelize(string)\n\nConverts underscored or dasherized string to a camelized one\n\n```javascript\n_('-moz-transform').camelize()\n=> 'MozTransform'\n```\n\n**classify** _.classify(string)\n\nConverts string to camelized class name\n\n```javascript\n_('some_class_name').classify()\n=> 'SomeClassName'\n```\n\n**underscored** _.underscored(string)\n\nConverts a camelized or dasherized string into an underscored one\n\n```javascript\n_('MozTransform').underscored()\n=> 'moz_transform'\n```\n\n**dasherize** _.dasherize(string)\n\nConverts a underscored or camelized string into an dasherized one\n\n```javascript\n_('MozTransform').dasherize()\n=> '-moz-transform'\n```\n\n**humanize** _.humanize(string)\n\nConverts an underscored, camelized, or dasherized string into a humanized one.\nAlso removes beginning and ending whitespace, and removes the postfix '_id'.\n\n```javascript\n_(' capitalize dash-CamelCase_underscore trim ').humanize()\n=> 'Capitalize dash camel case underscore trim'\n```\n\n**trim** _.trim(string, [characters])\n\ntrims defined characters from begining and ending of the string.\nDefaults to whitespace characters.\n\n```javascript\n_.trim(\" foobar \")\n=> \"foobar\"\n\n_.trim(\"_-foobar-_\", \"_-\")\n=> \"foobar\"\n```\n\n\n**ltrim** _.ltrim(string, [characters])\n\nLeft trim. Similar to trim, but only for left side.\n\n\n**rtrim** _.rtrim(string, [characters])\n\nRight trim. Similar to trim, but only for right side.\n\n**truncate** _.truncate(string, length, truncateString)\n\n```javascript\n_('Hello world').truncate(5)\n=> 'Hello...'\n\n_('Hello').truncate(10)\n=> 'Hello'\n```\n\n**prune** _.prune(string, length, pruneString)\n\nElegant version of truncate.\nMakes sure the pruned string does not exceed the original length.\nAvoid half-chopped words when truncating.\n\n```javascript\n_('Hello, world').prune(5)\n=> 'Hello...'\n\n_('Hello, world').prune(8)\n=> 'Hello...'\n\n_('Hello, world').prune(5, ' (read a lot more)')\n=> 'Hello, world' (as adding \"(read a lot more)\" would be longer than the original string)\n\n_('Hello, cruel world').prune(15)\n=> 'Hello, cruel...'\n\n_('Hello').prune(10)\n=> 'Hello'\n```\n\n**words** _.words(str, delimiter=\" \")\n\nSplit string by delimiter (String or RegExp), ' ' by default.\n\n```javascript\n_.words(\"I love you\")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I_love_you\", \"_\")\n=> [\"I\",\"love\",\"you\"]\n\n_.words(\"I-love-you\", /-/)\n=> [\"I\",\"love\",\"you\"]\n```\n\n**sprintf** _.sprintf(string format, *arguments)\n\nC like string formatting.\nCredits goes to [Alexandru Marasteanu][o].\nFor more detailed documentation, see the [original page][o].\n\n[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript\n\n```javascript\n_.sprintf(\"%.1f\", 1.17)\n\"1.2\"\n```\n\n**pad** _.pad(str, length, [padStr, type])\n\npads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`\" \"`). `padStr` is truncated to a single character if necessary.\n\n```javascript\n_.pad(\"1\", 8)\n-> \" 1\";\n\n_.pad(\"1\", 8, '0')\n-> \"00000001\";\n\n_.pad(\"1\", 8, '0', 'right')\n-> \"10000000\";\n\n_.pad(\"1\", 8, '0', 'both')\n-> \"00001000\";\n\n_.pad(\"1\", 8, 'bleepblorp', 'both')\n-> \"bbbb1bbb\";\n```\n\n**lpad** _.lpad(str, length, [padStr])\n\nleft-pad a string. Alias for `pad(str, length, padStr, 'left')`\n\n```javascript\n_.lpad(\"1\", 8, '0')\n-> \"00000001\";\n```\n\n**rpad** _.rpad(str, length, [padStr])\n\nright-pad a string. Alias for `pad(str, length, padStr, 'right')`\n\n```javascript\n_.rpad(\"1\", 8, '0')\n-> \"10000000\";\n```\n\n**lrpad** _.lrpad(str, length, [padStr])\n\nleft/right-pad a string. Alias for `pad(str, length, padStr, 'both')`\n\n```javascript\n_.lrpad(\"1\", 8, '0')\n-> \"00001000\";\n```\n\n**center** alias for **lrpad**\n\n**ljust** alias for *rpad*\n\n**rjust** alias for *lpad*\n\n**toNumber** _.toNumber(string, [decimals])\n\nParse string to number. Returns NaN if string can't be parsed to number.\n\n```javascript\n_('2.556').toNumber()\n=> 3\n\n_('2.556').toNumber(1)\n=> 2.6\n```\n\n**strRight** _.strRight(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRight('_')\n=> \"is_a_test_string\";\n```\n\n**strRightBack** _.strRightBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strRightBack('_')\n=> \"string\";\n```\n\n**strLeft** _.strLeft(string, pattern)\n\nSearches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeft('_')\n=> \"This\";\n```\n\n**strLeftBack** _.strLeftBack(string, pattern)\n\nSearches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.\n\n```javascript\n_('This_is_a_test_string').strLeftBack('_')\n=> \"This_is_a_test\";\n```\n\n**stripTags**\n\nRemoves all html tags from string.\n\n```javascript\n_('a link').stripTags()\n=> 'a link'\n\n_('a link').stripTags()\n=> 'a linkalert(\"hello world!\")'\n```\n\n**toSentence** _.toSentence(array, [delimiter, lastDelimiter])\n\nJoin an array into a human readable sentence.\n\n```javascript\n_.toSentence(['jQuery', 'Mootools', 'Prototype'])\n=> 'jQuery, Mootools and Prototype';\n\n_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ')\n=> 'jQuery, Mootools unt Prototype';\n```\n\n**repeat** _.repeat(string, count, [separator])\n\nRepeats a string count times.\n\n```javascript\n_.repeat(\"foo\", 3)\n=> 'foofoofoo';\n\n_.repeat(\"foo\", 3, \"bar\")\n=> 'foobarfoobarfoo'\n```\n\n**slugify** _.slugify(string)\n\nTransform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash.\n\n```javascript\n_.slugify(\"Un éléphant à l'orée du bois\")\n=> 'un-elephant-a-loree-du-bois';\n```\n\n***Caution: this function is charset dependent***\n\n## Roadmap ##\n\nAny suggestions or bug reports are welcome. Just email me or more preferably open an issue.\n\n## Changelog ##\n\n### 2.0.0 ###\n\n* Added prune, humanize functions\n* Added _.string (_.str) namespace for Underscore.string library\n* Removed includes function\n\n#### Problems\n\nWe lose two things for `include` and `reverse` methods from `_.string`:\n\n* Calls like `_('foobar').include('bar')` aren't available;\n* Chaining isn't available too.\n\nBut if you need this functionality you can create aliases for conflict functions which will be convenient for you:\n\n```javascript\n_.mixin({\n includeString: _.str.include,\n reverseString: _.str.reverse\n})\n\n// Now wrapper calls and chaining are available.\n_('foobar').chain().reverseString().includeString('rab').value()\n```\n\n#### Standalone Usage\n\nIf you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias\nBut of course you can just reassign `_` variable with `_.string`\n\n```javascript\n_ = _.string\n```\n### 2.2.0 ###\n\n* Capitalize method behavior changed\n* Various perfomance tweaks\n\n### 2.1.1###\n\n* Fixed words method bug\n* Added classify method\n\n### 2.1.0 ###\n\n* AMD support\n* Added toSentence method\n* Added slugify method\n* Lots of speed optimizations\n\n### 2.0.0 ###\n\nFor upgrading to this version you need to mix in Underscore.string library to Underscore object:\n\n```javascript\n_.mixin(_.string.exports());\n```\n\nand all non-conflict Underscore.string functions will be available through Underscore object.\nAlso function `includes` has been removed, you should replace this function by `_.str.include`\nor create alias `_.includes = _.str.include` and all your code will work fine.\n\n### 1.1.6 ###\n\n* Fixed reverse and truncate\n* Added isBlank, stripTags, inlude(alias for includes)\n* Added uglifier compression\n\n### 1.1.5 ###\n\n* Added strRight, strRightBack, strLeft, strLeftBack\n\n### 1.1.4 ###\n\n* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust\n* Integration with Underscore 1.1.6\n\n### 1.1.3 ###\n\n* Added methods: underscored, camelize, dasherize\n* Support newer version of npm\n\n### 1.1.2 ###\n\n* Created functions: lines, chars, words functions\n\n### 1.0.2 ###\n\n* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible)\n* Removed 'reverse' function, because this function override underscore.js 'reverse'\n\n## Contribute ##\n\n* Fork & pull request. Don't forget about tests.\n* If you planning add some feature please create issue before.\n\nOtherwise changes will be rejected.\n\n## Contributors list ##\n\n* Esa-Matti Suuronen (),\n* Edward Tsech ,\n* Sasha Koss (),\n* Vladimir Dronnikov ,\n* Pete Kruckenberg (),\n* Paul Chavard (),\n* Ed Finkler ()\n* Pavel Pravosud \n* Anton Lindqvist ()\n\n## Licence ##\n\nThe MIT License\n\nCopyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org\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", + "readmeFilename": "README.markdown", + "_id": "underscore.string@2.2.1", + "dist": { + "shasum": "f07c95c30e6906045470659c51ab365d882c8b8e" + }, + "_from": "underscore.string@~2.2.0rc", + "_resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz" +} diff --git a/node_modules/grunt/node_modules/underscore.string/test/run-qunit.js b/node_modules/grunt/node_modules/underscore.string/test/run-qunit.js new file mode 100644 index 000000000..326658ed7 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/run-qunit.js @@ -0,0 +1,44 @@ +function waitFor(test, complete, timeout) { + var result, start = new Date().getTime() + setInterval(function interval() { + if ((new Date().getTime() - start < timeout) && !result) { + result = test() + } else { + if (!result) { + phantom.exit(1) + } else { + complete() + clearInterval(interval) + } + } + }, 100) +} + + +var page = new WebPage() + +page.onConsoleMessage = function(msg) { + console.log(msg) +} + +page.open(phantom.args[0], function(status) { + waitFor(function() { + return page.evaluate(function(){ + var el = document.getElementById('qunit-testresult') + return el && el.innerText.match('completed') + }) + }, function() { + var failures = page.evaluate(function() { + var el = document.getElementById('qunit-testresult'), + fails = document.getElementsByClassName('fail') + + for (var i = 0; i < fails.length; i++) + console.log(fails[i].innerText) + + console.log(el.innerText) + + return parseInt(el.getElementsByClassName('failed')[0].innerHTML) + }) + phantom.exit(failures > 0 ? 1 : 0) + }, 10000) +}) \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/test/speed.js b/node_modules/grunt/node_modules/underscore.string/test/speed.js new file mode 100644 index 000000000..43464147d --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/speed.js @@ -0,0 +1,138 @@ +(function() { + + JSLitmus.test('trimNoNative', function() { + return _.trim(" foobar ", " "); + }); + + JSLitmus.test('trim', function() { + return _.trim(" foobar "); + }); + + JSLitmus.test('trim object-oriented', function() { + return _(" foobar ").trim(); + }); + + JSLitmus.test('trim jQuery', function() { + return jQuery.trim(" foobar "); + }); + + JSLitmus.test('ltrimp', function() { + return _.ltrim(" foobar ", " "); + }); + + JSLitmus.test('rtrimp', function() { + return _.rtrim(" foobar ", " "); + }); + + JSLitmus.test('startsWith', function() { + return _.startsWith("foobar", "foo"); + }); + + JSLitmus.test('endsWith', function() { + return _.endsWith("foobar", "xx"); + }); + + JSLitmus.test('chop', function(){ + return _('whitespace').chop(2); + }); + + JSLitmus.test('count', function(){ + return _('Hello worls').count('l'); + }); + + JSLitmus.test('insert', function() { + return _('Hello ').insert(6, 'world'); + }); + + JSLitmus.test('splice', function() { + return _('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'); + }); + + JSLitmus.test('succ', function(){ + var let = 'a', alphabet = []; + + for (var i=0; i < 26; i++) { + alphabet.push(let); + let = _(let).succ(); + } + + return alphabet; + }); + + JSLitmus.test('titleize', function(){ + return _('the titleize string method').titleize(); + }); + + JSLitmus.test('truncate', function(){ + return _('Hello world').truncate(5); + }); + + JSLitmus.test('prune', function(){ + return _('Hello world').prune(5); + }); + + JSLitmus.test('isBlank', function(){ + return _('').isBlank(); + }); + + JSLitmus.test('escapeHTML', function(){ + _('
          Blah blah blah
          ').escapeHTML(); + }); + + JSLitmus.test('unescapeHTML', function(){ + _('<div>Blah blah blah</div>').unescapeHTML(); + }); + + JSLitmus.test('reverse', function(){ + _('Hello World').reverse(); + }); + + JSLitmus.test('pad default', function(){ + _('foo').pad(12); + }); + + JSLitmus.test('pad hash left', function(){ + _('foo').pad(12, '#'); + }); + + JSLitmus.test('pad hash right', function(){ + _('foo').pad(12, '#', 'right'); + }); + + JSLitmus.test('pad hash both', function(){ + _('foo').pad(12, '#', 'both'); + }); + + JSLitmus.test('pad hash both longPad', function(){ + _('foo').pad(12, 'f00f00f00', 'both'); + }); + + JSLitmus.test('toNumber', function(){ + _('10.232323').toNumber(2); + }); + + JSLitmus.test('strRight', function(){ + _('aaa_bbb_ccc').strRight('_'); + }); + + JSLitmus.test('strRightBack', function(){ + _('aaa_bbb_ccc').strRightBack('_'); + }); + + JSLitmus.test('strLeft', function(){ + _('aaa_bbb_ccc').strLeft('_'); + }); + + JSLitmus.test('strLeftBack', function(){ + _('aaa_bbb_ccc').strLeftBack('_'); + }); + + JSLitmus.test('join', function(){ + _('separator').join(1, 2, 3, 4, 5, 6, 7, 8, 'foo', 'bar', 'lol', 'wut'); + }); + + JSLitmus.test('slugify', function(){ + _("Un éléphant à l'orée du bois").slugify(); + }); + +})(); diff --git a/node_modules/grunt/node_modules/underscore.string/test/strings.js b/node_modules/grunt/node_modules/underscore.string/test/strings.js new file mode 100644 index 000000000..f700abf10 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/strings.js @@ -0,0 +1,438 @@ +$(document).ready(function() { + + // Include Underscore.string methods to Underscore namespace + _.mixin(_.str.exports()); + + module("String extensions"); + + test("Strings: trim", function() { + equals(_.trim(123), "123", "Non string"); + equals(_(" foo").trim(), "foo"); + equals(_("foo ").trim(), "foo"); + equals(_(" foo ").trim(), "foo"); + equals(_(" foo ").trim(), "foo"); + equals(_(" foo ", " ").trim(), "foo", "Manually set whitespace"); + + equals(_("ffoo").trim("f"), "oo"); + equals(_("ooff").trim("f"), "oo"); + equals(_("ffooff").trim("f"), "oo"); + + + equals(_("_-foobar-_").trim("_-"), "foobar"); + + equals(_("http://foo/").trim("/"), "http://foo"); + equals(_("c:\\").trim('\\'), "c:"); + + equals(_(123).trim(), '123'); + equals(_(123).trim(3), '12'); + }); + + test("Strings: ltrim", function() { + equals(_(" foo").ltrim(), "foo"); + equals(_(" foo").ltrim(), "foo"); + equals(_("foo ").ltrim(), "foo "); + equals(_(" foo ").ltrim(), "foo "); + + + equals(_("ffoo").ltrim("f"), "oo"); + equals(_("ooff").ltrim("f"), "ooff"); + equals(_("ffooff").ltrim("f"), "ooff"); + + equals(_("_-foobar-_").ltrim("_-"), "foobar-_"); + + equals(_(123).ltrim(1), '23'); + }); + + test("Strings: rtrim", function() { + equals(_("http://foo/").rtrim("/"), "http://foo", 'clean trailing slash'); + equals(_(" foo").rtrim(), " foo"); + equals(_("foo ").rtrim(), "foo"); + equals(_("foo ").rtrim(), "foo"); + equals(_("foo bar ").rtrim(), "foo bar"); + equals(_(" foo ").rtrim(), " foo"); + + equals(_("ffoo").rtrim("f"), "ffoo"); + equals(_("ooff").rtrim("f"), "oo"); + equals(_("ffooff").rtrim("f"), "ffoo"); + + equals(_("_-foobar-_").rtrim("_-"), "_-foobar"); + + equals(_(123).rtrim(3), '12'); + }); + + test("Strings: capitalize", function() { + equals(_("fabio").capitalize(), "Fabio", 'First letter is upper case'); + equals(_.capitalize("fabio"), "Fabio", 'First letter is upper case'); + equals(_.capitalize('FOO'), 'FOO', 'Other letters unchanged'); + equals(_(123).capitalize(), "123", "Non string"); + }); + + test("Strings: join", function() { + equals(_.join("", "foo", "bar"), "foobar", 'basic join'); + equals(_.join("", 1, "foo", 2), "1foo2", 'join numbers and strings'); + equals(_.join(" ","foo", "bar"), "foo bar", 'join with spaces'); + equals(_.join("1", "2", "2"), "212", 'join number strings'); + equals(_.join(1, 2, 2), "212", 'join numbers'); + equals(_(" ").join("foo", "bar"), "foo bar", 'join object oriented'); + }); + + test("Strings: reverse", function() { + equals(_.str.reverse("foo"), "oof" ); + equals(_.str.reverse("foobar"), "raboof" ); + equals(_.str.reverse("foo bar"), "rab oof" ); + equals(_.str.reverse("saippuakauppias"), "saippuakauppias" ); + equals(_.str.reverse(123), "321", "Non string"); + equals(_.str.reverse(123.45), "54.321", "Non string"); + }); + + test("Strings: clean", function() { + equals(_(" foo bar ").clean(), "foo bar"); + equals(_(123).clean(), "123"); + }); + + test("Strings: sprintf", function() { + // Should be very tested function already. Thanks to + // http://www.diveintojavascript.com/projects/sprintf-for-javascript + equals(_.sprintf("Hello %s", "me"), "Hello me", 'basic'); + equals(_("Hello %s").sprintf("me"), "Hello me", 'object'); + equals(_("hello %s").chain().sprintf("me").capitalize().value(), "Hello me", 'Chaining works'); + equals(_.sprintf("%.1f", 1.22222), "1.2", 'round'); + equals(_.sprintf("%.1f", 1.17), "1.2", 'round 2'); + equals(_.sprintf("%(id)d - %(name)s", {id: 824, name: "Hello World"}), "824 - Hello World", 'Named replacements work'); + equals(_.sprintf("%(args[0].id)d - %(args[1].name)s", {args: [{id: 824}, {name: "Hello World"}]}), "824 - Hello World", 'Named replacements with arrays work'); + }); + + + test("Strings: vsprintf", function() { + equals(_.vsprintf("Hello %s", ["me"]), "Hello me", 'basic'); + equals(_("Hello %s").vsprintf(["me"]), "Hello me", 'object'); + equals(_("hello %s").chain().vsprintf(["me"]).capitalize().value(), "Hello me", 'Chaining works'); + equals(_.vsprintf("%.1f", [1.22222]), "1.2", 'round'); + equals(_.vsprintf("%.1f", [1.17]), "1.2", 'round 2'); + equals(_.vsprintf("%(id)d - %(name)s", [{id: 824, name: "Hello World"}]), "824 - Hello World", 'Named replacement works'); + equals(_.vsprintf("%(args[0].id)d - %(args[1].name)s", [{args: [{id: 824}, {name: "Hello World"}]}]), "824 - Hello World", 'Named replacement with arrays works'); + }); + + test("Strings: startsWith", function() { + ok(_("foobar").startsWith("foo"), 'foobar starts with foo'); + ok(!_("oobar").startsWith("foo"), 'oobar does not start with foo'); + ok(_(12345).startsWith(123), '12345 starts with 123'); + ok(!_(2345).startsWith(123), '2345 does not start with 123'); + }); + + test("Strings: endsWith", function() { + ok(_("foobar").endsWith("bar"), 'foobar ends with bar'); + ok(_.endsWith("foobar", "bar"), 'foobar ends with bar'); + ok(_.endsWith("00018-0000062.Plone.sdh264.1a7264e6912a91aa4a81b64dc5517df7b8875994.mp4", "mp4"), 'endsWith .mp4'); + ok(!_("fooba").endsWith("bar"), 'fooba does not end with bar'); + ok(_.endsWith(12345, 45), '12345 ends with 45'); + ok(!_.endsWith(12345, 6), '12345 does not end with 6'); + }); + + test("Strings: include", function() { + ok(_.str.include("foobar", "bar"), 'foobar includes bar'); + ok(!_.str.include("foobar", "buzz"), 'foobar does not includes buzz'); + ok(_.str.include(12345, 34), '12345 includes 34'); + ok(!_.str.contains(12345, 6), '12345 does not includes 6'); + }); + + test('String: chop', function(){ + ok(_('whitespace').chop(2).length === 5, "output ['wh','it','es','pa','ce']"); + ok(_('whitespace').chop(3).length === 4, "output ['whi','tes','pac','e']"); + ok(_('whitespace').chop()[0].length === 10, "output ['whitespace']"); + ok(_(12345).chop(1).length === 5, "output ['1','2','3','4','5']"); + }); + + test('String: clean', function(){ + equals(_.clean(' foo bar '), 'foo bar'); + equals(_.clean(1), '1'); + }); + + test('String: count', function(){ + equals(_('Hello world').count('l'), 3); + equals(_('Hello world').count('Hello'), 1); + equals(_('Hello world').count('foo'), 0); + equals(_('x.xx....x.x').count('x'), 5); + equals(_(12345).count(1), 1); + equals(_(11345).count(1), 2); + }); + + test('String: insert', function(){ + equals(_('Hello ').insert(6, 'Jessy'), 'Hello Jessy'); + equals(_('Hello ').insert(100, 'Jessy'), 'Hello Jessy'); + equals(_(12345).insert(6, 'Jessy'), '12345Jessy'); + }); + + test('String: splice', function(){ + equals(_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'), + 'https://edtsech@bitbucket.org/epeli/underscore.strings'); + equals(_.splice(12345, 1, 2, 321), '132145', 'Non strings'); + }); + + test('String: succ', function(){ + equals(_('a').succ(), 'b'); + equals(_('A').succ(), 'B'); + equals(_('+').succ(), ','); + equals(_(1).succ(), '2'); + }); + + test('String: titleize', function(){ + equals(_('the titleize string method').titleize(), 'The Titleize String Method'); + equals(_('the titleize string method').titleize(), 'The Titleize String Method'); + equals(_(123).titleize(), '123'); + }); + + test('String: camelize', function(){ + equals(_('the_camelize_string_method').camelize(), 'theCamelizeStringMethod'); + equals(_('-the-camelize-string-method').camelize(), 'TheCamelizeStringMethod'); + equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_(' the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_(123).camelize(), '123'); + }); + + test('String: underscored', function(){ + equals(_('the-underscored-string-method').underscored(), 'the_underscored_string_method'); + equals(_('theUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equals(_('TheUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equals(_(' the underscored string method').underscored(), 'the_underscored_string_method'); + equals(_(123).underscored(), '123'); + }); + + test('String: dasherize', function(){ + equals(_('the_dasherize_string_method').dasherize(), 'the-dasherize-string-method'); + equals(_('TheDasherizeStringMethod').dasherize(), '-the-dasherize-string-method'); + equals(_('thisIsATest').dasherize(), 'this-is-a-test'); + equals(_('this Is A Test').dasherize(), 'this-is-a-test'); + equals(_('thisIsATest123').dasherize(), 'this-is-a-test123'); + equals(_('123thisIsATest').dasherize(), '123this-is-a-test'); + equals(_('the dasherize string method').dasherize(), 'the-dasherize-string-method'); + equals(_('the dasherize string method ').dasherize(), 'the-dasherize-string-method'); + equals(_('téléphone').dasherize(), 'téléphone'); + equals(_('foo$bar').dasherize(), 'foo$bar'); + equals(_(123).dasherize(), '123'); + }); + + test('String: camelize', function(){ + equals(_.camelize('-moz-transform'), 'MozTransform'); + equals(_.camelize('webkit-transform'), 'webkitTransform'); + equals(_.camelize('under_scored'), 'underScored'); + equals(_.camelize(' with spaces'), 'withSpaces'); + }); + + test('String: join', function(){ + equals(_.join(1, 2, 3, 4), '21314'); + equals(_.join('|', 'foo', 'bar', 'baz'), 'foo|bar|baz'); + }); + + test('String: classify', function(){ + equals(_.classify(1), '1'); + equals(_('some_class_name').classify(), 'SomeClassName'); + }); + + test('String: humanize', function(){ + equals(_('the_humanize_string_method').humanize(), 'The humanize string method'); + equals(_('ThehumanizeStringMethod').humanize(), 'Thehumanize string method'); + equals(_('the humanize string method').humanize(), 'The humanize string method'); + equals(_('the humanize_id string method_id').humanize(), 'The humanize id string method'); + equals(_('the humanize string method ').humanize(), 'The humanize string method'); + equals(_(' capitalize dash-CamelCase_underscore trim ').humanize(), 'Capitalize dash camel case underscore trim'); + equals(_(123).humanize(), '123'); + }); + + test('String: truncate', function(){ + equals(_('Hello world').truncate(6, 'read more'), 'Hello read more'); + equals(_('Hello world').truncate(5), 'Hello...'); + equals(_('Hello').truncate(10), 'Hello'); + equals(_(1234567890).truncate(5), '12345...'); + }); + + test('String: prune', function(){ + equals(_('Hello, cruel world').prune(6, ' read more'), 'Hello read more'); + equals(_('Hello, world').prune(5, 'read a lot more'), 'Hello, world'); + equals(_('Hello, world').prune(5), 'Hello...'); + equals(_('Hello, world').prune(8), 'Hello...'); + equals(_('Hello, cruel world').prune(15), 'Hello, cruel...'); + equals(_('Hello world').prune(22), 'Hello world'); + equals(_('Привет, жестокий мир').prune(6, ' read more'), 'Привет read more'); + equals(_('Привет, мир').prune(6, 'read a lot more'), 'Привет, мир'); + equals(_('Привет, мир').prune(6), 'Привет...'); + equals(_('Привет, мир').prune(8), 'Привет...'); + equals(_('Привет, жестокий мир').prune(16), 'Привет, жестокий...'); + equals(_('Привет, мир').prune(22), 'Привет, мир'); + equals(_(123).prune(10), '123'); + equals(_(123).prune(1,1), '11'); + }); + + test('String: isBlank', function(){ + ok(_('').isBlank()); + ok(_(' ').isBlank()); + ok(_('\n').isBlank()); + ok(!_('a').isBlank()); + ok(!_('0').isBlank()); + ok(!_(0).isBlank()); + }); + + test('String: escapeHTML', function(){ + equals(_('
          Blah & "blah" & \'blah\'
          ').escapeHTML(), + '<div>Blah & "blah" & 'blah'</div>'); + equals(_('<').escapeHTML(), '&lt;'); + equals(_(5).escapeHTML(), '5'); + // equals(_(undefined).escapeHTML(), ''); + }); + + test('String: unescapeHTML', function(){ + equals(_('<div>Blah & "blah" & 'blah'</div>').unescapeHTML(), + '
          Blah & "blah" & \'blah\'
          '); + equals(_('&lt;').unescapeHTML(), '<'); + equals(_(''').unescapeHTML(), "'"); + equals(_(''').unescapeHTML(), "'"); + equals(_('J').unescapeHTML(), "J"); + equals(_('J').unescapeHTML(), "J"); + equals(_('J').unescapeHTML(), "J"); + equals(_('&_#39;').unescapeHTML(), "&_#39;"); + equals(_(''_;').unescapeHTML(), "'_;"); + equals(_('&#38;').unescapeHTML(), "&"); + equals(_('&amp;').unescapeHTML(), "&"); + equals(_(5).unescapeHTML(), '5'); + // equals(_(undefined).unescapeHTML(), ''); + }); + + test('String: words', function() { + equals(_("I love you!").words().length, 3); + equals(_(" I love you! ").words().length, 3); + equals(_("I_love_you!").words('_').length, 3); + equals(_("I-love-you!").words(/-/).length, 3); + equals(_(123).words().length, 1); + }); + + test('String: chars', function() { + equals(_("Hello").chars().length, 5); + equals(_(123).chars().length, 3); + }); + + test('String: lines', function() { + equals(_("Hello\nWorld").lines().length, 2); + equals(_("Hello World").lines().length, 1); + equals(_(123).lines().length, 1); + }); + + test('String: pad', function() { + equals(_("1").pad(8), ' 1'); + equals(_(1).pad(8), ' 1'); + equals(_("1").pad(8, '0'), '00000001'); + equals(_("1").pad(8, '0', 'left'), '00000001'); + equals(_("1").pad(8, '0', 'right'), '10000000'); + equals(_("1").pad(8, '0', 'both'), '00001000'); + equals(_("foo").pad(8, '0', 'both'), '000foo00'); + equals(_("foo").pad(7, '0', 'both'), '00foo00'); + equals(_("foo").pad(7, '!@$%dofjrofj', 'both'), '!!foo!!'); + }); + + test('String: lpad', function() { + equals(_("1").lpad(8), ' 1'); + equals(_(1).lpad(8), ' 1'); + equals(_("1").lpad(8, '0'), '00000001'); + equals(_("1").lpad(8, '0', 'left'), '00000001'); + }); + + test('String: rpad', function() { + equals(_("1").rpad(8), '1 '); + equals(_(1).lpad(8), ' 1'); + equals(_("1").rpad(8, '0'), '10000000'); + equals(_("foo").rpad(8, '0'), 'foo00000'); + equals(_("foo").rpad(7, '0'), 'foo0000'); + }); + + test('String: lrpad', function() { + equals(_("1").lrpad(8), ' 1 '); + equals(_(1).lrpad(8), ' 1 '); + equals(_("1").lrpad(8, '0'), '00001000'); + equals(_("foo").lrpad(8, '0'), '000foo00'); + equals(_("foo").lrpad(7, '0'), '00foo00'); + equals(_("foo").lrpad(7, '!@$%dofjrofj'), '!!foo!!'); + }); + + test('String: toNumber', function() { + deepEqual(_("not a number").toNumber(), Number.NaN); + equals(_(0).toNumber(), 0); + equals(_("0").toNumber(), 0); + equals(_("0000").toNumber(), 0); + equals(_("2.345").toNumber(), 2); + equals(_("2.345").toNumber(NaN), 2); + equals(_("2.345").toNumber(2), 2.35); + equals(_("2.344").toNumber(2), 2.34); + equals(_("2").toNumber(2), 2.00); + equals(_(2).toNumber(2), 2.00); + equals(_(-2).toNumber(), -2); + equals(_("-2").toNumber(), -2); + }); + + test('String: strRight', function() { + equals(_("This_is_a_test_string").strRight("_"), "is_a_test_string"); + equals(_("This_is_a_test_string").strRight("string"), ""); + equals(_("This_is_a_test_string").strRight(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRight(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRight("-"), "This_is_a_test_string"); + equals(_(12345).strRight(2), "345"); + }); + + test('String: strRightBack', function() { + equals(_("This_is_a_test_string").strRightBack("_"), "string"); + equals(_("This_is_a_test_string").strRightBack("string"), ""); + equals(_("This_is_a_test_string").strRightBack(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRightBack(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRightBack("-"), "This_is_a_test_string"); + equals(_(12345).strRightBack(2), "345"); + }); + + test('String: strLeft', function() { + equals(_("This_is_a_test_string").strLeft("_"), "This"); + equals(_("This_is_a_test_string").strLeft("This"), ""); + equals(_("This_is_a_test_string").strLeft(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeft(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeft("-"), "This_is_a_test_string"); + equals(_(123454321).strLeft(3), "12"); + }); + + test('String: strLeftBack', function() { + equals(_("This_is_a_test_string").strLeftBack("_"), "This_is_a_test"); + equals(_("This_is_a_test_string").strLeftBack("This"), ""); + equals(_("This_is_a_test_string").strLeftBack(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeftBack(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeftBack("-"), "This_is_a_test_string"); + equals(_(123454321).strLeftBack(3), "123454"); + }); + + test('Strings: stripTags', function() { + equals(_('a link').stripTags(), 'a link'); + equals(_('a link + + + + + + + + +

          Underscore.string Test Suite

          +

          +

          +
            +
            +

            Underscore.string Speed Suite

            + +
            + + diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html b/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html new file mode 100644 index 000000000..9854c1711 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html @@ -0,0 +1,18 @@ + + + + Underscore.strings Test Suite + + + + + + + + +

            Underscore.string Test Suite

            +

            +

            +
              + + diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js new file mode 100644 index 000000000..b3b1ce15e --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js @@ -0,0 +1,166 @@ +$(document).ready(function() { + + module("Arrays"); + + test("arrays: first", function() { + equals(_.first([1,2,3]), 1, 'can pull out the first element of an array'); + equals(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); + equals(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first'); + equals(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first'); + equals(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first'); + var result = (function(){ return _.first(arguments); })(4, 3, 2, 1); + equals(result, 4, 'works on an arguments object.'); + result = _.map([[1,2,3],[1,2,3]], _.first); + equals(result.join(','), '1,1', 'works well with _.map'); + }); + + test("arrays: rest", function() { + var numbers = [1, 2, 3, 4]; + equals(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()'); + equals(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)'); + equals(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index'); + var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4); + equals(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.rest); + equals(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map'); + }); + + test("arrays: initial", function() { + equals(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()'); + equals(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index'); + var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4); + equals(result.join(", "), "1, 2, 3", 'initial works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.initial); + equals(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map'); + }); + + test("arrays: last", function() { + equals(_.last([1,2,3]), 3, 'can pull out the last element of an array'); + equals(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last'); + equals(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last'); + equals(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last'); + var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4); + equals(result, 4, 'works on an arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.last); + equals(result.join(','), '3,3', 'works well with _.map'); + }); + + test("arrays: compact", function() { + equals(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); + var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3); + equals(result, 3, 'works on an arguments object'); + }); + + test("arrays: flatten", function() { + if (window.JSON) { + var list = [1, [2], [3, [[[4]]]]]; + equals(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays'); + equals(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays'); + var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); + equals(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object'); + } + }); + + test("arrays: without", function() { + var list = [1, 2, 1, 0, 3, 1, 4]; + equals(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object'); + var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4); + equals(result.join(', '), '2, 3, 4', 'works on an arguments object'); + + var list = [{one : 1}, {two : 2}]; + ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.'); + ok(_.without(list, list[0]).length == 1, 'ditto.'); + }); + + test("arrays: uniq", function() { + var list = [1, 2, 1, 3, 1, 4]; + equals(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array'); + + var list = [1, 1, 1, 2, 2, 3]; + equals(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster'); + + var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}]; + var iterator = function(value) { return value.name; }; + equals(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator'); + + var iterator = function(value) { return value +1; }; + var list = [1, 2, 2, 3, 4, 4]; + equals(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array'); + + var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4); + equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); + }); + + test("arrays: intersection", function() { + var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; + equals(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); + equals(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection'); + var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); + equals(result.join(''), 'moe', 'works on an arguments object'); + }); + + test("arrays: union", function() { + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); + equals(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); + + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); + equals(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays'); + }); + + test("arrays: difference", function() { + var result = _.difference([1, 2, 3], [2, 30, 40]); + equals(result.join(' '), '1 3', 'takes the difference of two arrays'); + + var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); + equals(result.join(' '), '3 4', 'takes the difference of three arrays'); + }); + + test('arrays: zip', function() { + var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; + var stooges = _.zip(names, ages, leaders); + equals(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths'); + }); + + test("arrays: indexOf", function() { + var numbers = [1, 2, 3]; + numbers.indexOf = null; + equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function'); + var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3); + equals(result, 1, 'works on an arguments object'); + equals(_.indexOf(null, 2), -1, 'handles nulls properly'); + + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.indexOf(numbers, num, true); + equals(index, -1, '35 is not in the list'); + + numbers = [10, 20, 30, 40, 50]; num = 40; + index = _.indexOf(numbers, num, true); + equals(index, 3, '40 is in the list'); + + numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; + index = _.indexOf(numbers, num, true); + equals(index, 1, '40 is in the list'); + }); + + test("arrays: lastIndexOf", function() { + var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; + numbers.lastIndexOf = null; + equals(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); + equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); + var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0); + equals(result, 5, 'works on an arguments object'); + equals(_.indexOf(null, 2), -1, 'handles nulls properly'); + }); + + test("arrays: range", function() { + equals(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array'); + equals(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); + equals(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); + equals(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array'); + equals(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); + equals(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); + equals(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); + equals(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs'); + }); + +}); diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js new file mode 100644 index 000000000..0e3d5f385 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js @@ -0,0 +1,59 @@ +$(document).ready(function() { + + module("Chaining"); + + test("chaining: map/flatten/reduce", function() { + var lyrics = [ + "I'm a lumberjack and I'm okay", + "I sleep all night and I work all day", + "He's a lumberjack and he's okay", + "He sleeps all night and he works all day" + ]; + var counts = _(lyrics).chain() + .map(function(line) { return line.split(''); }) + .flatten() + .reduce(function(hash, l) { + hash[l] = hash[l] || 0; + hash[l]++; + return hash; + }, {}).value(); + ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); + }); + + test("chaining: select/reject/sortBy", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _(numbers).chain().select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("chaining: select/reject/sortBy in functional style", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _.chain(numbers).select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("chaining: reverse/concat/unshift/pop/map", function() { + var numbers = [1,2,3,4,5]; + numbers = _(numbers).chain() + .reverse() + .concat([5, 5, 5]) + .unshift(17) + .pop() + .map(function(n){ return n * 2; }) + .value(); + equals(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); + }); + +}); diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js new file mode 100644 index 000000000..cff9763ce --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js @@ -0,0 +1,270 @@ +$(document).ready(function() { + + module("Collections"); + + test("collections: each", function() { + _.each([1, 2, 3], function(num, i) { + equals(num, i + 1, 'each iterators provide value and iteration count'); + }); + + var answers = []; + _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5}); + equals(answers.join(', '), '5, 10, 15', 'context object property accessed'); + + answers = []; + _.forEach([1, 2, 3], function(num){ answers.push(num); }); + equals(answers.join(', '), '1, 2, 3', 'aliased as "forEach"'); + + answers = []; + var obj = {one : 1, two : 2, three : 3}; + obj.constructor.prototype.four = 4; + _.each(obj, function(value, key){ answers.push(key); }); + equals(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); + delete obj.constructor.prototype.four; + + answer = null; + _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); + ok(answer, 'can reference the original collection from inside the iterator'); + + answers = 0; + _.each(null, function(){ ++answers; }); + equals(answers, 0, 'handles a null properly'); + }); + + test('collections: map', function() { + var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'doubled numbers'); + + doubled = _.collect([1, 2, 3], function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'aliased as "collect"'); + + var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3}); + equals(tripled.join(', '), '3, 6, 9', 'tripled numbers with context'); + + var doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers'); + + var ids = _.map($('div.underscore-test').children(), function(n){ return n.id; }); + ok(_.include(ids, 'qunit-header'), 'can use collection methods on NodeLists'); + + var ids = _.map(document.images, function(n){ return n.id; }); + ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); + + var ifnull = _.map(null, function(){}); + ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly'); + + var length = _.map(Array(2), function(v) { return v; }).length; + equals(length, 2, "can preserve a sparse array's length"); + }); + + test('collections: reduce', function() { + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'can sum up an array'); + + var context = {multiplier : 3}; + sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context); + equals(sum, 18, 'can reduce with a context object'); + + sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'aliased as "inject"'); + + sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'OO-style reduce'); + + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }); + equals(sum, 6, 'default initial value'); + + var ifnull; + try { + _.reduce(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + equals(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + + var sparseArray = []; + sparseArray[0] = 20; + sparseArray[2] = -5; + equals(_.reduce(sparseArray, function(a, b){ return a - b; }), 25, 'initially-sparse arrays with no memo'); + }); + + test('collections: reduceRight', function() { + var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equals(list, 'bazbarfoo', 'can perform right folds'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equals(list, 'bazbarfoo', 'aliased as "foldr"'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }); + equals(list, 'bazbarfoo', 'default initial value'); + + var ifnull; + try { + _.reduceRight(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + + equals(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + + var sparseArray = []; + sparseArray[0] = 20; + sparseArray[2] = -5; + equals(_.reduceRight(sparseArray, function(a, b){ return a - b; }), -25, 'initially-sparse arrays with no memo'); + }); + + test('collections: detect', function() { + var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; }); + equals(result, 2, 'found the first "2" and broke the loop'); + }); + + test('collections: select', function() { + var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(evens.join(', '), '2, 4, 6', 'selected each even number'); + + evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(evens.join(', '), '2, 4, 6', 'aliased as "filter"'); + }); + + test('collections: reject', function() { + var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(odds.join(', '), '1, 3, 5', 'rejected each even number'); + }); + + test('collections: all', function() { + ok(_.all([], _.identity), 'the empty set'); + ok(_.all([true, true, true], _.identity), 'all true values'); + ok(!_.all([true, false, true], _.identity), 'one false value'); + ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers'); + ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number'); + ok(_.every([true, true, true], _.identity), 'aliased as "every"'); + }); + + test('collections: any', function() { + var nativeSome = Array.prototype.some; + Array.prototype.some = null; + ok(!_.any([]), 'the empty set'); + ok(!_.any([false, false, false]), 'all false values'); + ok(_.any([false, false, true]), 'one true value'); + ok(_.any([null, 0, 'yes', false]), 'a string'); + ok(!_.any([null, 0, '', false]), 'falsy values'); + ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers'); + ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number'); + ok(_.some([false, false, true]), 'aliased as "some"'); + Array.prototype.some = nativeSome; + }); + + test('collections: include', function() { + ok(_.include([1,2,3], 2), 'two is in the array'); + ok(!_.include([1,3,9], 2), 'two is not in the array'); + ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values'); + ok(_([1,2,3]).include(2), 'OO-style include'); + }); + + test('collections: invoke', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, 'sort'); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + test('collections: invoke w/ function reference', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, Array.prototype.sort); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + // Relevant when using ClojureScript + test('collections: invoke when strings have a call method', function() { + String.prototype.call = function(){return 42;} + var list = [[5, 1, 7], [3, 2, 1]]; + var s = "foo"; + equals(s.call(), 42, "call function exists"); + var result = _.invoke(list, 'sort'); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + delete String.prototype.call; + equals(s.call, undefined, "call function removed"); + }); + + test('collections: pluck', function() { + var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; + equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); + }); + + test('collections: max', function() { + equals(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); + + var neg = _.max([1, 2, 3], function(num){ return -num; }); + equals(neg, 1, 'can perform a computation-based max'); + + equals(-Infinity, _.max({}), 'Maximum value of an empty object'); + equals(-Infinity, _.max([]), 'Maximum value of an empty array'); + }); + + test('collections: min', function() { + equals(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); + + var neg = _.min([1, 2, 3], function(num){ return -num; }); + equals(neg, 3, 'can perform a computation-based min'); + + equals(Infinity, _.min({}), 'Minimum value of an empty object'); + equals(Infinity, _.min([]), 'Minimum value of an empty array'); + }); + + test('collections: sortBy', function() { + var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; + people = _.sortBy(people, function(person){ return person.age; }); + equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age'); + }); + + test('collections: groupBy', function() { + var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); + ok('0' in parity && '1' in parity, 'created a group for each value'); + equals(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group'); + + var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; + var grouped = _.groupBy(list, 'length'); + equals(grouped['3'].join(' '), 'one two six ten'); + equals(grouped['4'].join(' '), 'four five nine'); + equals(grouped['5'].join(' '), 'three seven eight'); + }); + + test('collections: sortedIndex', function() { + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.sortedIndex(numbers, num); + equals(index, 3, '35 should be inserted at index 3'); + }); + + test('collections: shuffle', function() { + var numbers = _.range(10); + var shuffled = _.shuffle(numbers).sort(); + notStrictEqual(numbers, shuffled, 'original object is unmodified'); + equals(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle'); + }); + + test('collections: toArray', function() { + ok(!_.isArray(arguments), 'arguments object is not an array'); + ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); + var a = [1,2,3]; + ok(_.toArray(a) !== a, 'array is cloned'); + equals(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements'); + + var numbers = _.toArray({one : 1, two : 2, three : 3}); + equals(numbers.join(', '), '1, 2, 3', 'object flattened into array'); + }); + + test('collections: size', function() { + equals(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); + }); + +}); diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js new file mode 100644 index 000000000..78721af16 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js @@ -0,0 +1,198 @@ +$(document).ready(function() { + + module("Functions"); + + test("functions: bind", function() { + var context = {name : 'moe'}; + var func = function(arg) { return "name: " + (this.name || arg); }; + var bound = _.bind(func, context); + equals(bound(), 'name: moe', 'can bind a function to a context'); + + bound = _(func).bind(context); + equals(bound(), 'name: moe', 'can do OO-style binding'); + + bound = _.bind(func, null, 'curly'); + equals(bound(), 'name: curly', 'can bind without specifying a context'); + + func = function(salutation, name) { return salutation + ': ' + name; }; + func = _.bind(func, this, 'hello'); + equals(func('moe'), 'hello: moe', 'the function was partially applied in advance'); + + var func = _.bind(func, this, 'curly'); + equals(func(), 'hello: curly', 'the function was completely applied in advance'); + + var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; + func = _.bind(func, this, 'hello', 'moe', 'curly'); + equals(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); + + func = function(context, message) { equals(this, context, message); }; + _.bind(func, 0, 0, 'can bind a function to `0`')(); + _.bind(func, '', '', 'can bind a function to an empty string')(); + _.bind(func, false, false, 'can bind a function to `false`')(); + + // These tests are only meaningful when using a browser without a native bind function + // To test this with a modern browser, set underscore's nativeBind to undefined + var F = function () { return this; }; + var Boundf = _.bind(F, {hello: "moe curly"}); + equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5"); + equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); + }); + + test("functions: bindAll", function() { + var curly = {name : 'curly'}, moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + curly.getName = moe.getName; + _.bindAll(moe, 'getName', 'sayHi'); + curly.sayHi = moe.sayHi; + equals(curly.getName(), 'name: curly', 'unbound function is bound to current object'); + equals(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); + + curly = {name : 'curly'}; + moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + _.bindAll(moe); + curly.sayHi = moe.sayHi; + equals(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object'); + }); + + test("functions: memoize", function() { + var fib = function(n) { + return n < 2 ? n : fib(n - 1) + fib(n - 2); + }; + var fastFib = _.memoize(fib); + equals(fib(10), 55, 'a memoized version of fibonacci produces identical results'); + equals(fastFib(10), 55, 'a memoized version of fibonacci produces identical results'); + + var o = function(str) { + return str; + }; + var fastO = _.memoize(o); + equals(o('toString'), 'toString', 'checks hasOwnProperty'); + equals(fastO('toString'), 'toString', 'checks hasOwnProperty'); + }); + + asyncTest("functions: delay", 2, function() { + var delayed = false; + _.delay(function(){ delayed = true; }, 100); + setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50); + setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150); + }); + + asyncTest("functions: defer", 1, function() { + var deferred = false; + _.defer(function(bool){ deferred = bool; }, true); + _.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50); + }); + + asyncTest("functions: throttle", 2, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); throttledIncr(); + setTimeout(throttledIncr, 70); + setTimeout(throttledIncr, 120); + setTimeout(throttledIncr, 140); + setTimeout(throttledIncr, 190); + setTimeout(throttledIncr, 220); + setTimeout(throttledIncr, 240); + _.delay(function(){ ok(counter == 1, "incr was called immediately"); }, 30); + _.delay(function(){ ok(counter == 4, "incr was throttled"); start(); }, 400); + }); + + asyncTest("functions: throttle arguments", 2, function() { + var value = 0; + var update = function(val){ value = val; }; + var throttledUpdate = _.throttle(update, 100); + throttledUpdate(1); throttledUpdate(2); throttledUpdate(3); + setTimeout(function(){ throttledUpdate(4); }, 120); + setTimeout(function(){ throttledUpdate(5); }, 140); + setTimeout(function(){ throttledUpdate(6); }, 250); + _.delay(function(){ equals(value, 1, "updated to latest value"); }, 40); + _.delay(function(){ equals(value, 6, "updated to latest value"); start(); }, 400); + }); + + asyncTest("functions: throttle once", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); + _.delay(function(){ ok(counter == 1, "incr was called once"); start(); }, 220); + }); + + asyncTest("functions: throttle twice", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); + _.delay(function(){ ok(counter == 2, "incr was called twice"); start(); }, 220); + }); + + asyncTest("functions: debounce", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var debouncedIncr = _.debounce(incr, 50); + debouncedIncr(); debouncedIncr(); debouncedIncr(); + setTimeout(debouncedIncr, 30); + setTimeout(debouncedIncr, 60); + setTimeout(debouncedIncr, 90); + setTimeout(debouncedIncr, 120); + setTimeout(debouncedIncr, 150); + _.delay(function(){ ok(counter == 1, "incr was debounced"); start(); }, 220); + }); + + test("functions: once", function() { + var num = 0; + var increment = _.once(function(){ num++; }); + increment(); + increment(); + equals(num, 1); + }); + + test("functions: wrap", function() { + var greet = function(name){ return "hi: " + name; }; + var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); + equals(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function'); + + var inner = function(){ return "Hello "; }; + var obj = {name : "Moe"}; + obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); + equals(obj.hi(), "Hello Moe"); + + var noop = function(){}; + var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); }); + var ret = wrapped(['whats', 'your'], 'vector', 'victor'); + same(ret, [noop, ['whats', 'your'], 'vector', 'victor']); + }); + + test("functions: compose", function() { + var greet = function(name){ return "hi: " + name; }; + var exclaim = function(sentence){ return sentence + '!'; }; + var composed = _.compose(exclaim, greet); + equals(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); + + composed = _.compose(greet, exclaim); + equals(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); + }); + + test("functions: after", function() { + var testAfter = function(afterAmount, timesCalled) { + var afterCalled = 0; + var after = _.after(afterAmount, function() { + afterCalled++; + }); + while (timesCalled--) after(); + return afterCalled; + }; + + equals(testAfter(5, 5), 1, "after(N) should fire after being called N times"); + equals(testAfter(5, 4), 0, "after(N) should not fire unless called N times"); + equals(testAfter(0, 0), 1, "after(0) should fire immediately"); + }); + +}); diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js new file mode 100644 index 000000000..0105d608a --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js @@ -0,0 +1,535 @@ +$(document).ready(function() { + + module("Objects"); + + test("objects: keys", function() { + var exception = /object/; + equals(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); + // the test above is not safe because it relies on for-in enumeration order + var a = []; a[1] = 0; + equals(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95'); + raises(function() { _.keys(null); }, exception, 'throws an error for `null` values'); + raises(function() { _.keys(void 0); }, exception, 'throws an error for `undefined` values'); + raises(function() { _.keys(1); }, exception, 'throws an error for number primitives'); + raises(function() { _.keys('a'); }, exception, 'throws an error for string primitives'); + raises(function() { _.keys(true); }, exception, 'throws an error for boolean primitives'); + }); + + test("objects: values", function() { + equals(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object'); + }); + + test("objects: functions", function() { + var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; + ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); + + var Animal = function(){}; + Animal.prototype.run = function(){}; + equals(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype'); + }); + + test("objects: extend", function() { + var result; + equals(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another'); + equals(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination'); + equals(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden'); + result = _.extend({x:'x'}, {a:'a'}, {b:'b'}); + ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects'); + result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'}); + ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); + result = _.extend({}, {a: void 0, b: null}); + equals(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); + }); + + test("objects: defaults", function() { + var result; + var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"}; + + _.defaults(options, {zero: 1, one: 10, twenty: 20}); + equals(options.zero, 0, 'value exists'); + equals(options.one, 1, 'value exists'); + equals(options.twenty, 20, 'default applied'); + + _.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"}); + equals(options.empty, "", 'value exists'); + ok(_.isNaN(options.nan), "NaN isn't overridden"); + equals(options.word, "word", 'new value is added, first one wins'); + }); + + test("objects: clone", function() { + var moe = {name : 'moe', lucky : [13, 27, 34]}; + var clone = _.clone(moe); + equals(clone.name, 'moe', 'the clone as the attributes of the original'); + + clone.name = 'curly'; + ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original'); + + clone.lucky.push(101); + equals(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); + + equals(_.clone(undefined), void 0, 'non objects should not be changed by clone'); + equals(_.clone(1), 1, 'non objects should not be changed by clone'); + equals(_.clone(null), null, 'non objects should not be changed by clone'); + }); + + test("objects: isEqual", function() { + function First() { + this.value = 1; + } + First.prototype.value = 1; + function Second() { + this.value = 1; + } + Second.prototype.value = 2; + + // Basic equality and identity comparisons. + ok(_.isEqual(null, null), "`null` is equal to `null`"); + ok(_.isEqual(), "`undefined` is equal to `undefined`"); + + ok(!_.isEqual(0, -0), "`0` is not equal to `-0`"); + ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`"); + ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`"); + ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`"); + + // String object and primitive comparisons. + ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal"); + ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal"); + ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal"); + ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives"); + + ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal"); + ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal"); + ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal"); + + // Number object and primitive comparisons. + ok(_.isEqual(75, 75), "Identical number primitives are equal"); + ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal"); + ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives"); + ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal"); + ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`"); + + ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal"); + ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal"); + + // Comparisons involving `NaN`. + ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`"); + ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`"); + ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`"); + ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`"); + + // Boolean object and primitive comparisons. + ok(_.isEqual(true, true), "Identical boolean primitives are equal"); + ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal"); + ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans"); + ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal"); + + // Common type coercions. + ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`"); + ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal"); + ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal"); + ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values"); + ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal"); + ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal"); + ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal"); + ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal"); + ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal"); + + // Dates. + ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal"); + ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal"); + ok(!_.isEqual(new Date(2009, 11, 13), { + getTime: function(){ + return 12606876e5; + } + }), "Date objects and objects with a `getTime` method are not equal"); + ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal"); + + // Functions. + ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal"); + + // RegExps. + ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal"); + ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal"); + ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal"); + ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps"); + ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal"); + + // Empty arrays, array-like objects, and object literals. + ok(_.isEqual({}, {}), "Empty object literals are equal"); + ok(_.isEqual([], []), "Empty array literals are equal"); + ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal"); + ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal."); + ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects"); + + ok(!_.isEqual({}, []), "Object literals and array literals are not equal"); + ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays"); + + // Arrays with primitive and object values. + ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal"); + ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal"); + + // Multi-dimensional arrays. + var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared"); + + // Overwrite the methods defined in ES 5.1 section 15.4.4. + a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; + b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; + + // Array elements and properties. + ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal"); + a.push("White Rocks"); + ok(!_.isEqual(a, b), "Arrays of different lengths are not equal"); + a.push("East Boulder"); + b.push("Gunbarrel Ranch", "Teller Farm"); + ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal"); + + // Sparse arrays. + ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal"); + ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty"); + + // According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined` + // elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined` + // values are equivalent. + if (0 in [undefined]) { + ok(!_.isEqual(Array(3), [undefined, undefined, undefined]), "Sparse and dense arrays are not equal"); + ok(!_.isEqual([undefined, undefined, undefined], Array(3)), "Commutative equality is implemented for sparse and dense arrays"); + } + + // Simple objects. + ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal"); + ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal"); + ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal"); + ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects"); + ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent"); + + // `A` contains nested objects and arrays. + a = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + + // `B` contains equivalent nested objects and arrays. + b = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared"); + + // Instances. + ok(_.isEqual(new First, new First), "Object instances are equal"); + ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal"); + ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal"); + ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined"); + + // Circular Arrays. + (a = []).push(a); + (b = []).push(b); + ok(_.isEqual(a, b), "Arrays containing circular references are equal"); + a.push(new String("Larry")); + b.push(new String("Larry")); + ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal"); + a.push("Shemp"); + b.push("Curly"); + ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal"); + + // Circular Objects. + a = {abc: null}; + b = {abc: null}; + a.abc = a; + b.abc = b; + ok(_.isEqual(a, b), "Objects containing circular references are equal"); + a.def = 75; + b.def = 75; + ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal"); + a.def = new Number(75); + b.def = new Number(63); + ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal"); + + // Cyclic Structures. + a = [{abc: null}]; + b = [{abc: null}]; + (a[0].abc = a).push(a); + (b[0].abc = b).push(b); + ok(_.isEqual(a, b), "Cyclic structures are equal"); + a[0].def = "Larry"; + b[0].def = "Larry"; + ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal"); + a[0].def = new String("Larry"); + b[0].def = new String("Curly"); + ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal"); + + // Complex Circular References. + a = {foo: {b: {foo: {c: {foo: null}}}}}; + b = {foo: {b: {foo: {c: {foo: null}}}}}; + a.foo.b.foo.c.foo = a; + b.foo.b.foo.c.foo = b; + ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal"); + + // Chaining. + ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); + equals(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained'); + + // Custom `isEqual` methods. + var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}}; + var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}}; + + ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods'); + ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods'); + ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal'); + ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods'); + + // Custom `isEqual` methods - comparing different types + LocalizedString = (function() { + function LocalizedString(id) { this.id = id; this.string = (this.id===10)? 'Bonjour': ''; } + LocalizedString.prototype.isEqual = function(that) { + if (_.isString(that)) return this.string == that; + else if (that instanceof LocalizedString) return this.id == that.id; + return false; + }; + return LocalizedString; + })(); + var localized_string1 = new LocalizedString(10), localized_string2 = new LocalizedString(10), localized_string3 = new LocalizedString(11); + ok(_.isEqual(localized_string1, localized_string2), 'comparing same typed instances with same ids'); + ok(!_.isEqual(localized_string1, localized_string3), 'comparing same typed instances with different ids'); + ok(_.isEqual(localized_string1, 'Bonjour'), 'comparing different typed instances with same values'); + ok(_.isEqual('Bonjour', localized_string1), 'comparing different typed instances with same values'); + ok(!_.isEqual('Bonjour', localized_string3), 'comparing two localized strings with different ids'); + ok(!_.isEqual(localized_string1, 'Au revoir'), 'comparing different typed instances with different values'); + ok(!_.isEqual('Au revoir', localized_string1), 'comparing different typed instances with different values'); + + // Custom `isEqual` methods - comparing with serialized data + Date.prototype.toJSON = function() { + return { + _type:'Date', + year:this.getUTCFullYear(), + month:this.getUTCMonth(), + day:this.getUTCDate(), + hours:this.getUTCHours(), + minutes:this.getUTCMinutes(), + seconds:this.getUTCSeconds() + }; + }; + Date.prototype.isEqual = function(that) { + var this_date_components = this.toJSON(); + var that_date_components = (that instanceof Date) ? that.toJSON() : that; + delete this_date_components['_type']; delete that_date_components['_type'] + return _.isEqual(this_date_components, that_date_components); + }; + + var date = new Date(); + var date_json = { + _type:'Date', + year:date.getUTCFullYear(), + month:date.getUTCMonth(), + day:date.getUTCDate(), + hours:date.getUTCHours(), + minutes:date.getUTCMinutes(), + seconds:date.getUTCSeconds() + }; + + ok(_.isEqual(date_json, date), 'serialized date matches date'); + ok(_.isEqual(date, date_json), 'date matches serialized date'); + }); + + test("objects: isEmpty", function() { + ok(!_([1]).isEmpty(), '[1] is not empty'); + ok(_.isEmpty([]), '[] is empty'); + ok(!_.isEmpty({one : 1}), '{one : 1} is not empty'); + ok(_.isEmpty({}), '{} is empty'); + ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); + ok(_.isEmpty(null), 'null is empty'); + ok(_.isEmpty(), 'undefined is empty'); + ok(_.isEmpty(''), 'the empty string is empty'); + ok(!_.isEmpty('moe'), 'but other strings are not'); + + var obj = {one : 1}; + delete obj.one; + ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); + }); + + // Setup remote variables for iFrame tests. + var iframe = document.createElement('iframe'); + jQuery(iframe).appendTo(document.body); + var iDoc = iframe.contentDocument || iframe.contentWindow.document; + iDoc.write( + "" + ); + iDoc.close(); + + test("objects: isElement", function() { + ok(!_.isElement('div'), 'strings are not dom elements'); + ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); + ok(_.isElement(iElement), 'even from another frame'); + }); + + test("objects: isArguments", function() { + var args = (function(){ return arguments; })(1, 2, 3); + ok(!_.isArguments('string'), 'a string is not an arguments object'); + ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); + ok(_.isArguments(args), 'but the arguments object is an arguments object'); + ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); + ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.'); + ok(_.isArguments(iArguments), 'even from another frame'); + }); + + test("objects: isObject", function() { + ok(_.isObject(arguments), 'the arguments object is object'); + ok(_.isObject([1, 2, 3]), 'and arrays'); + ok(_.isObject($('html')[0]), 'and DOM element'); + ok(_.isObject(iElement), 'even from another frame'); + ok(_.isObject(function () {}), 'and functions'); + ok(_.isObject(iFunction), 'even from another frame'); + ok(!_.isObject(null), 'but not null'); + ok(!_.isObject(undefined), 'and not undefined'); + ok(!_.isObject('string'), 'and not string'); + ok(!_.isObject(12), 'and not number'); + ok(!_.isObject(true), 'and not boolean'); + ok(_.isObject(new String('string')), 'but new String()'); + }); + + test("objects: isArray", function() { + ok(!_.isArray(arguments), 'the arguments object is not an array'); + ok(_.isArray([1, 2, 3]), 'but arrays are'); + ok(_.isArray(iArray), 'even from another frame'); + }); + + test("objects: isString", function() { + ok(!_.isString(document.body), 'the document body is not a string'); + ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); + ok(_.isString(iString), 'even from another frame'); + }); + + test("objects: isNumber", function() { + ok(!_.isNumber('string'), 'a string is not a number'); + ok(!_.isNumber(arguments), 'the arguments object is not a number'); + ok(!_.isNumber(undefined), 'undefined is not a number'); + ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); + ok(_.isNumber(NaN), 'NaN *is* a number'); + ok(_.isNumber(Infinity), 'Infinity is a number'); + ok(_.isNumber(iNumber), 'even from another frame'); + ok(!_.isNumber('1'), 'numeric strings are not numbers'); + }); + + test("objects: isBoolean", function() { + ok(!_.isBoolean(2), 'a number is not a boolean'); + ok(!_.isBoolean("string"), 'a string is not a boolean'); + ok(!_.isBoolean("false"), 'the string "false" is not a boolean'); + ok(!_.isBoolean("true"), 'the string "true" is not a boolean'); + ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); + ok(!_.isBoolean(undefined), 'undefined is not a boolean'); + ok(!_.isBoolean(NaN), 'NaN is not a boolean'); + ok(!_.isBoolean(null), 'null is not a boolean'); + ok(_.isBoolean(true), 'but true is'); + ok(_.isBoolean(false), 'and so is false'); + ok(_.isBoolean(iBoolean), 'even from another frame'); + }); + + test("objects: isFunction", function() { + ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); + ok(!_.isFunction('moe'), 'strings are not functions'); + ok(_.isFunction(_.isFunction), 'but functions are'); + ok(_.isFunction(iFunction), 'even from another frame'); + }); + + test("objects: isDate", function() { + ok(!_.isDate(100), 'numbers are not dates'); + ok(!_.isDate({}), 'objects are not dates'); + ok(_.isDate(new Date()), 'but dates are'); + ok(_.isDate(iDate), 'even from another frame'); + }); + + test("objects: isRegExp", function() { + ok(!_.isRegExp(_.identity), 'functions are not RegExps'); + ok(_.isRegExp(/identity/), 'but RegExps are'); + ok(_.isRegExp(iRegExp), 'even from another frame'); + }); + + test("objects: isNaN", function() { + ok(!_.isNaN(undefined), 'undefined is not NaN'); + ok(!_.isNaN(null), 'null is not NaN'); + ok(!_.isNaN(0), '0 is not NaN'); + ok(_.isNaN(NaN), 'but NaN is'); + ok(_.isNaN(iNaN), 'even from another frame'); + }); + + test("objects: isNull", function() { + ok(!_.isNull(undefined), 'undefined is not null'); + ok(!_.isNull(NaN), 'NaN is not null'); + ok(_.isNull(null), 'but null is'); + ok(_.isNull(iNull), 'even from another frame'); + }); + + test("objects: isUndefined", function() { + ok(!_.isUndefined(1), 'numbers are defined'); + ok(!_.isUndefined(null), 'null is defined'); + ok(!_.isUndefined(false), 'false is defined'); + ok(!_.isUndefined(NaN), 'NaN is defined'); + ok(_.isUndefined(), 'nothing is undefined'); + ok(_.isUndefined(undefined), 'undefined is undefined'); + ok(_.isUndefined(iUndefined), 'even from another frame'); + }); + + if (window.ActiveXObject) { + test("objects: IE host objects", function() { + var xml = new ActiveXObject("Msxml2.DOMDocument.3.0"); + ok(!_.isNumber(xml)); + ok(!_.isBoolean(xml)); + ok(!_.isNaN(xml)); + ok(!_.isFunction(xml)); + ok(!_.isNull(xml)); + ok(!_.isUndefined(xml)); + }); + } + + test("objects: tap", function() { + var intercepted = null; + var interceptor = function(obj) { intercepted = obj; }; + var returned = _.tap(1, interceptor); + equals(intercepted, 1, "passes tapped object to interceptor"); + equals(returned, 1, "returns tapped object"); + + returned = _([1,2,3]).chain(). + map(function(n){ return n * 2; }). + max(). + tap(interceptor). + value(); + ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); + }); +}); diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js new file mode 100644 index 000000000..86663a237 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js @@ -0,0 +1,70 @@ +(function() { + + var numbers = []; + for (var i=0; i<1000; i++) numbers.push(i); + var objects = _.map(numbers, function(n){ return {num : n}; }); + var randomized = _.sortBy(numbers, function(){ return Math.random(); }); + + JSLitmus.test('_.each()', function() { + var timesTwo = []; + _.each(numbers, function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('_(list).each()', function() { + var timesTwo = []; + _(numbers).each(function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('jQuery.each()', function() { + var timesTwo = []; + jQuery.each(numbers, function(){ timesTwo.push(this * 2); }); + return timesTwo; + }); + + JSLitmus.test('_.map()', function() { + return _.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('jQuery.map()', function() { + return jQuery.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('_.pluck()', function() { + return _.pluck(objects, 'num'); + }); + + JSLitmus.test('_.uniq()', function() { + return _.uniq(randomized); + }); + + JSLitmus.test('_.uniq() (sorted)', function() { + return _.uniq(numbers, true); + }); + + JSLitmus.test('_.sortBy()', function() { + return _.sortBy(numbers, function(num){ return -num; }); + }); + + JSLitmus.test('_.isEqual()', function() { + return _.isEqual(numbers, randomized); + }); + + JSLitmus.test('_.keys()', function() { + return _.keys(objects); + }); + + JSLitmus.test('_.values()', function() { + return _.values(objects); + }); + + JSLitmus.test('_.intersect()', function() { + return _.intersect(numbers, randomized); + }); + + JSLitmus.test('_.range()', function() { + return _.range(1000); + }); + +})(); \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js new file mode 100644 index 000000000..68c39dc57 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js @@ -0,0 +1,27 @@ +(function() { + + var func = function(){}; + var date = new Date(); + var str = "a string"; + var numbers = []; + for (var i=0; i<1000; i++) numbers.push(i); + var objects = _.map(numbers, function(n){ return {num : n}; }); + var randomized = _.sortBy(numbers, function(){ return Math.random(); }); + + JSLitmus.test('_.isNumber', function() { + return _.isNumber(1000) + }); + + JSLitmus.test('_.newIsNumber', function() { + return _.newIsNumber(1000) + }); + + JSLitmus.test('_.isNumber(NaN)', function() { + return _.isNumber(NaN) + }); + + JSLitmus.test('_.newIsNumber(NaN)', function() { + return _.newIsNumber(NaN) + }); + +})(); \ No newline at end of file diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html new file mode 100644 index 000000000..bd34f9dd7 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html @@ -0,0 +1,19 @@ + + + + Underscore Temporary Tests + + + + + + + +

              Underscore Temporary Tests

              +

              + A page for temporary speed tests, used for developing faster implementations + of existing Underscore methods. +

              +
              + + diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html new file mode 100644 index 000000000..77f2f3a22 --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html @@ -0,0 +1,43 @@ + + + + Underscore Test Suite + + + + + + + + + + + + + + + +
              +

              Underscore Test Suite

              +

              +

              +
                +
                +

                Underscore Speed Suite

                +

                + A representative sample of the functions are benchmarked here, to provide + a sense of how fast they might run in different browsers. + Each iteration runs on an array of 1000 elements.

                + For example, the 'intersect' test measures the number of times you can + find the intersection of two thousand-element arrays in one second. +

                +
                + + +
                + + diff --git a/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js new file mode 100644 index 000000000..7bc5cb44b --- /dev/null +++ b/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js @@ -0,0 +1,155 @@ +$(document).ready(function() { + + module("Utility"); + + test("utility: noConflict", function() { + var underscore = _.noConflict(); + ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state."); + var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]); + equals(intersection.join(', '), '1, 2', 'but the intersection function still works'); + window._ = underscore; + }); + + test("utility: identity", function() { + var moe = {name : 'moe'}; + equals(_.identity(moe), moe, 'moe is the same as his identity'); + }); + + test("utility: uniqueId", function() { + var ids = [], i = 0; + while(i++ < 100) ids.push(_.uniqueId()); + equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); + }); + + test("utility: times", function() { + var vals = []; + _.times(3, function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); + // + vals = []; + _(3).times(function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); + }); + + test("utility: mixin", function() { + _.mixin({ + myReverse: function(string) { + return string.split('').reverse().join(''); + } + }); + equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); + equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); + }); + + test("utility: _.escape", function() { + equals(_.escape("Curly & Moe"), "Curly & Moe"); + equals(_.escape("Curly & Moe"), "Curly &amp; Moe"); + }); + + test("utility: template", function() { + var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); + var result = basicTemplate({thing : 'This'}); + equals(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); + + var sansSemicolonTemplate = _.template("A <% this %> B"); + equals(sansSemicolonTemplate(), "A B"); + + var backslashTemplate = _.template("<%= thing %> is \\ridanculous"); + equals(backslashTemplate({thing: 'This'}), "This is \\ridanculous"); + + var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); + equals(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); + + var fancyTemplate = _.template("
                  <% \ + for (key in people) { \ + %>
                • <%= people[key] %>
                • <% } %>
                "); + result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); + equals(result, "
                • Moe
                • Larry
                • Curly
                ", 'can run arbitrary javascript in templates'); + + var escapedCharsInJavascriptTemplate = _.template("
                  <% _.each(numbers.split('\\n'), function(item) { %>
                • <%= item %>
                • <% }) %>
                "); + result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); + equals(result, "
                • one
                • two
                • three
                • four
                ", 'Can use escaped characters (e.g. \\n) in Javascript'); + + var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
                \">
                <% }); %>"); + result = namespaceCollisionTemplate({ + pageCount: 3, + thumbnails: { + 1: "p1-thumbnail.gif", + 2: "p2-thumbnail.gif", + 3: "p3-thumbnail.gif" + } + }); + equals(result, "3 p3-thumbnail.gif
                "); + + var noInterpolateTemplate = _.template("

                Just some text. Hey, I know this is silly but it aids consistency.

                "); + result = noInterpolateTemplate(); + equals(result, "

                Just some text. Hey, I know this is silly but it aids consistency.

                "); + + var quoteTemplate = _.template("It's its, not it's"); + equals(quoteTemplate({}), "It's its, not it's"); + + var quoteInStatementAndBody = _.template("<%\ + if(foo == 'bar'){ \ + %>Statement quotes and 'quotes'.<% } %>"); + equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'."); + + var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); + equals(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); + + var template = _.template("<%- value %>"); + var result = template({value: "